From 900c0d30b94223c6d80c319f59ae510f04683c58 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Wed, 27 Jul 2022 11:25:44 -0700 Subject: [PATCH] *: Drop module level app property module.app property usage is greatly reduced because setup() and force_upgrade() method are now part of App class instead of at the module level. Remove the remaining minor cases of usage and drop the property altogether. Signed-off-by: Sunil Mohan Adapa Reviewed-by: James Valleroy --- plinth/app.py | 2 +- plinth/modules/apache/__init__.py | 2 -- plinth/modules/avahi/__init__.py | 2 -- plinth/modules/backups/__init__.py | 2 -- plinth/modules/backups/views.py | 3 ++- plinth/modules/bepasty/__init__.py | 2 -- plinth/modules/bind/__init__.py | 2 -- plinth/modules/calibre/__init__.py | 2 -- plinth/modules/calibre/tests/test_views.py | 4 +-- plinth/modules/calibre/views.py | 6 +++-- plinth/modules/cockpit/__init__.py | 2 -- plinth/modules/config/__init__.py | 2 -- plinth/modules/coturn/__init__.py | 2 -- plinth/modules/coturn/views.py | 4 ++- plinth/modules/datetime/__init__.py | 2 -- plinth/modules/deluge/__init__.py | 2 -- plinth/modules/diagnostics/__init__.py | 2 -- plinth/modules/diagnostics/views.py | 2 +- plinth/modules/dynamicdns/__init__.py | 3 +-- plinth/modules/ejabberd/__init__.py | 8 ++++-- .../ejabberd/tests/test_turn_config.py | 6 +++-- plinth/modules/email/__init__.py | 3 ++- plinth/modules/firewall/__init__.py | 2 -- plinth/modules/gitweb/__init__.py | 4 +-- plinth/modules/gitweb/tests/test_views.py | 8 +++--- plinth/modules/gitweb/views.py | 13 ++++++---- plinth/modules/help/__init__.py | 2 -- plinth/modules/i2p/__init__.py | 2 -- plinth/modules/ikiwiki/__init__.py | 2 -- plinth/modules/ikiwiki/views.py | 25 +++++++++++-------- plinth/modules/infinoted/__init__.py | 2 -- plinth/modules/janus/__init__.py | 2 -- plinth/modules/janus/views.py | 5 ++-- plinth/modules/jsxc/__init__.py | 2 -- plinth/modules/letsencrypt/__init__.py | 2 -- plinth/modules/letsencrypt/views.py | 6 +++-- plinth/modules/matrixsynapse/__init__.py | 5 ++-- .../matrixsynapse/tests/test_turn_config.py | 6 +++-- plinth/modules/matrixsynapse/views.py | 6 +++-- plinth/modules/mediawiki/__init__.py | 2 -- plinth/modules/mediawiki/views.py | 7 ++++-- plinth/modules/minetest/__init__.py | 2 -- plinth/modules/minidlna/__init__.py | 7 +++--- plinth/modules/mumble/__init__.py | 4 +-- plinth/modules/mumble/views.py | 4 ++- plinth/modules/names/__init__.py | 2 -- plinth/modules/names/views.py | 4 +-- plinth/modules/networks/__init__.py | 2 -- plinth/modules/networks/views.py | 3 ++- plinth/modules/openvpn/__init__.py | 2 -- plinth/modules/openvpn/views.py | 3 ++- plinth/modules/pagekite/__init__.py | 2 -- plinth/modules/pagekite/utils.py | 4 +-- plinth/modules/performance/__init__.py | 2 -- plinth/modules/power/__init__.py | 2 -- plinth/modules/power/views.py | 20 +++++++++------ plinth/modules/privoxy/__init__.py | 2 -- plinth/modules/quassel/__init__.py | 2 -- plinth/modules/quassel/views.py | 5 ++-- plinth/modules/radicale/__init__.py | 2 -- plinth/modules/roundcube/__init__.py | 2 -- plinth/modules/rssbridge/__init__.py | 2 -- plinth/modules/samba/__init__.py | 2 -- plinth/modules/searx/__init__.py | 4 +-- plinth/modules/searx/views.py | 6 +++-- plinth/modules/security/__init__.py | 2 -- plinth/modules/security/views.py | 3 ++- plinth/modules/shaarli/__init__.py | 2 -- plinth/modules/shadowsocks/__init__.py | 2 -- plinth/modules/sharing/__init__.py | 2 -- plinth/modules/sharing/views.py | 6 +++-- plinth/modules/snapshot/__init__.py | 2 -- plinth/modules/snapshot/views.py | 16 +++++++----- plinth/modules/ssh/__init__.py | 2 -- plinth/modules/sso/__init__.py | 2 -- plinth/modules/storage/__init__.py | 2 -- plinth/modules/syncthing/__init__.py | 2 -- plinth/modules/tor/__init__.py | 4 +-- plinth/modules/tor/tests/test_tor.py | 6 +++-- plinth/modules/tor/utils.py | 7 +++--- plinth/modules/tor/views.py | 13 ++++++---- plinth/modules/transmission/__init__.py | 2 -- plinth/modules/ttrss/__init__.py | 2 -- plinth/modules/upgrades/__init__.py | 2 -- plinth/modules/users/__init__.py | 2 -- plinth/modules/wireguard/__init__.py | 2 -- plinth/modules/wordpress/__init__.py | 2 -- plinth/modules/zoph/__init__.py | 2 -- plinth/modules/zoph/views.py | 6 +++-- 89 files changed, 151 insertions(+), 200 deletions(-) diff --git a/plinth/app.py b/plinth/app.py index 63f0b4e4d..727db85db 100644 --- a/plinth/app.py +++ b/plinth/app.py @@ -552,7 +552,7 @@ def _initialize_module(module_name, module): cls for _, cls in module_classes if issubclass(cls, App) ] for app_class in app_classes: - module.app = app_class() + app_class() except Exception as exception: logger.exception('Exception while running init for %s: %s', module, exception) diff --git a/plinth/modules/apache/__init__.py b/plinth/modules/apache/__init__.py index 6d3e56158..ca567090e 100644 --- a/plinth/modules/apache/__init__.py +++ b/plinth/modules/apache/__init__.py @@ -15,8 +15,6 @@ from plinth.modules.letsencrypt.components import LetsEncrypt from plinth.package import Packages from plinth.utils import format_lazy, is_valid_user_name -app = None - class ApacheApp(app_module.App): """FreedomBox app for Apache web server.""" diff --git a/plinth/modules/avahi/__init__.py b/plinth/modules/avahi/__init__.py index 7c2d9b96f..f06bbf271 100644 --- a/plinth/modules/avahi/__init__.py +++ b/plinth/modules/avahi/__init__.py @@ -32,8 +32,6 @@ _description = [ 'hostile local network.'), box_name=_(cfg.box_name)) ] -app = None - class AvahiApp(app_module.App): """FreedomBox app for Avahi.""" diff --git a/plinth/modules/backups/__init__.py b/plinth/modules/backups/__init__.py index 34bdb79ad..0583af152 100644 --- a/plinth/modules/backups/__init__.py +++ b/plinth/modules/backups/__init__.py @@ -31,8 +31,6 @@ MANIFESTS_FOLDER = '/var/lib/plinth/backups-manifests/' # session variable name that stores when a backup file should be deleted SESSION_PATH_VARIABLE = 'fbx-backups-upload-path' -app = None - class BackupsApp(app_module.App): """FreedomBox app for backup and restore.""" diff --git a/plinth/modules/backups/views.py b/plinth/modules/backups/views.py index feb9b0fbe..4cb7fbfc0 100644 --- a/plinth/modules/backups/views.py +++ b/plinth/modules/backups/views.py @@ -20,6 +20,7 @@ from django.utils.translation import gettext as _ from django.utils.translation import gettext_lazy from django.views.generic import FormView, TemplateView, View +from plinth import app as app_module from plinth.errors import PlinthError from plinth.modules import backups, storage @@ -40,7 +41,7 @@ class IndexView(TemplateView): def get_context_data(self, **kwargs): """Return additional context for rendering the template.""" context = super().get_context_data(**kwargs) - context['app_info'] = backups.app.info + context['app_info'] = app_module.App.get('backups').info context['repositories'] = [ repository.get_view_content() for repository in get_repositories() ] diff --git a/plinth/modules/bepasty/__init__.py b/plinth/modules/bepasty/__init__.py index f1fda08f3..e97e8caf9 100644 --- a/plinth/modules/bepasty/__init__.py +++ b/plinth/modules/bepasty/__init__.py @@ -32,8 +32,6 @@ _description = [ 'their password from the list.'), ] -app = None - PERMISSIONS = { 'read': _('Read a file, if a web link to the file is available'), 'create': _('Create or upload files'), diff --git a/plinth/modules/bind/__init__.py b/plinth/modules/bind/__init__.py index ec267fe31..ff61d51f4 100644 --- a/plinth/modules/bind/__init__.py +++ b/plinth/modules/bind/__init__.py @@ -58,8 +58,6 @@ listen-on-v6 { any; }; }; ''' -app = None - class BindApp(app_module.App): """FreedomBox app for Bind.""" diff --git a/plinth/modules/calibre/__init__.py b/plinth/modules/calibre/__init__.py index dcfcc9828..93aeb164d 100644 --- a/plinth/modules/calibre/__init__.py +++ b/plinth/modules/calibre/__init__.py @@ -36,8 +36,6 @@ _description = [ 'the app. All users with access can use all the libraries.') ] -app = None - LIBRARY_NAME_PATTERN = r'[a-zA-Z0-9 _-]+' diff --git a/plinth/modules/calibre/tests/test_views.py b/plinth/modules/calibre/tests/test_views.py index 24ede010d..d1ee16747 100644 --- a/plinth/modules/calibre/tests/test_views.py +++ b/plinth/modules/calibre/tests/test_views.py @@ -100,7 +100,7 @@ def test_create_library_invalid_name(rf): assert response.status_code == 200 -@patch('plinth.modules.calibre.app') +@patch('plinth.app.App.get') def test_delete_library_confirmation_view(_app, rf): """Test that deleting library confirmation shows correct name.""" response, _ = make_request(rf.get(''), views.delete_library, @@ -110,7 +110,7 @@ def test_delete_library_confirmation_view(_app, rf): @patch('plinth.modules.calibre.delete_library') -@patch('plinth.modules.calibre.app') +@patch('plinth.app.App.get') def test_delete_library(_app, delete_library, rf): """Test that deleting a library works.""" response, messages = make_request(rf.post(''), views.delete_library, diff --git a/plinth/modules/calibre/views.py b/plinth/modules/calibre/views.py index 7e52b09c6..d8a9e6e5b 100644 --- a/plinth/modules/calibre/views.py +++ b/plinth/modules/calibre/views.py @@ -12,7 +12,9 @@ from django.urls import reverse_lazy from django.utils.translation import gettext as _ from django.views.generic.edit import FormView -from plinth import actions, views +from plinth import actions +from plinth import app as app_module +from plinth import views from plinth.modules import calibre from . import forms @@ -70,6 +72,6 @@ def delete_library(request, name): return redirect(reverse_lazy('calibre:index')) return TemplateResponse(request, 'calibre-delete-library.html', { - 'title': calibre.app.info.name, + 'title': app_module.App.get('calibre').info.name, 'name': name }) diff --git a/plinth/modules/cockpit/__init__.py b/plinth/modules/cockpit/__init__.py index ff5b704e8..53a89ec1b 100644 --- a/plinth/modules/cockpit/__init__.py +++ b/plinth/modules/cockpit/__init__.py @@ -35,8 +35,6 @@ _description = [ box_name=_(cfg.box_name), users_url=reverse_lazy('users:index')), ] -app = None - class CockpitApp(app_module.App): """FreedomBox app for Cockpit.""" diff --git a/plinth/modules/config/__init__.py b/plinth/modules/config/__init__.py index f80c8c1d9..80d2adb9e 100644 --- a/plinth/modules/config/__init__.py +++ b/plinth/modules/config/__init__.py @@ -34,8 +34,6 @@ FREEDOMBOX_APACHE_CONFIG = os.path.join(APACHE_CONF_ENABLED_DIR, 'freedombox.conf') ADVANCED_MODE_KEY = 'advanced_mode' -app = None - class ConfigApp(app_module.App): """FreedomBox app for basic system configuration.""" diff --git a/plinth/modules/coturn/__init__.py b/plinth/modules/coturn/__init__.py index 69311891b..71498f5e8 100644 --- a/plinth/modules/coturn/__init__.py +++ b/plinth/modules/coturn/__init__.py @@ -38,8 +38,6 @@ _description = [ e_url=reverse_lazy('ejabberd:index')), ] -app = None - logger = logging.getLogger(__name__) diff --git a/plinth/modules/coturn/views.py b/plinth/modules/coturn/views.py index 07073968a..25e6e46b7 100644 --- a/plinth/modules/coturn/views.py +++ b/plinth/modules/coturn/views.py @@ -7,6 +7,7 @@ from django.contrib import messages from django.utils.translation import gettext_lazy as _ import plinth.modules.coturn as coturn +from plinth import app as app_module from plinth import views from . import forms @@ -35,7 +36,8 @@ class CoturnAppView(views.AppView): data = form.cleaned_data if coturn.get_domain() != data['domain']: coturn.set_domain(data['domain']) - coturn.app.get_component('letsencrypt-coturn').setup_certificates() + app = app_module.App.get('coturn') + app.get_component('letsencrypt-coturn').setup_certificates() messages.success(self.request, _('Configuration updated')) return super().form_valid(form) diff --git a/plinth/modules/datetime/__init__.py b/plinth/modules/datetime/__init__.py index 5962fdba3..e51cd50cd 100644 --- a/plinth/modules/datetime/__init__.py +++ b/plinth/modules/datetime/__init__.py @@ -20,8 +20,6 @@ _description = [ 'in synchronization with servers on the Internet.') ] -app = None - class DateTimeApp(app_module.App): """FreedomBox app for date and time if time syncronization is unmanaged.""" diff --git a/plinth/modules/deluge/__init__.py b/plinth/modules/deluge/__init__.py index 9a6967edf..d6c65a743 100644 --- a/plinth/modules/deluge/__init__.py +++ b/plinth/modules/deluge/__init__.py @@ -24,8 +24,6 @@ _description = [ 'change it immediately after enabling this service.') ] -app = None - SYSTEM_USER = 'debian-deluged' diff --git a/plinth/modules/diagnostics/__init__.py b/plinth/modules/diagnostics/__init__.py index 6931e7162..169f917de 100644 --- a/plinth/modules/diagnostics/__init__.py +++ b/plinth/modules/diagnostics/__init__.py @@ -25,8 +25,6 @@ _description = [ 'expected.') ] -app = None - logger = logging.Logger(__name__) running_task = None diff --git a/plinth/modules/diagnostics/views.py b/plinth/modules/diagnostics/views.py index cff4451f1..3f2d66146 100644 --- a/plinth/modules/diagnostics/views.py +++ b/plinth/modules/diagnostics/views.py @@ -27,7 +27,7 @@ def index(request): return TemplateResponse( request, 'diagnostics.html', { - 'app_info': diagnostics.app.info, + 'app_info': App.get('diagnostics').info, 'is_running': is_running, 'results': results, 'refresh_page_sec': 3 if is_running else None diff --git a/plinth/modules/dynamicdns/__init__.py b/plinth/modules/dynamicdns/__init__.py index a87629454..79688396f 100644 --- a/plinth/modules/dynamicdns/__init__.py +++ b/plinth/modules/dynamicdns/__init__.py @@ -45,8 +45,6 @@ _description = [ 'target=\'_blank\'>freedns.afraid.org.'), ] -app = None - class DynamicDNSApp(app_module.App): """FreedomBox app for Dynamic DNS.""" @@ -221,6 +219,7 @@ def _update_dns_for_domain(domain): def update_dns(_data): """For all configured domains, check and up to date DNS records.""" config = get_config() + app = app_module.App.get('dynamicdns') if not app.is_enabled(): return diff --git a/plinth/modules/ejabberd/__init__.py b/plinth/modules/ejabberd/__init__.py index 43d2b39b3..1e768b019 100644 --- a/plinth/modules/ejabberd/__init__.py +++ b/plinth/modules/ejabberd/__init__.py @@ -46,8 +46,6 @@ _description = [ logger = logging.getLogger(__name__) -app = None - class EjabberdApp(app_module.App): """FreedomBox app for ejabberd.""" @@ -162,6 +160,7 @@ def on_pre_hostname_change(sender, old_hostname, new_hostname, **kwargs): """ del sender # Unused del kwargs # Unused + app = app_module.App.get('ejabberd') if app.needs_setup(): return @@ -175,6 +174,7 @@ def on_post_hostname_change(sender, old_hostname, new_hostname, **kwargs): """Update ejabberd config after hostname change.""" del sender # Unused del kwargs # Unused + app = app_module.App.get('ejabberd') if app.needs_setup(): return @@ -187,6 +187,7 @@ def on_post_hostname_change(sender, old_hostname, new_hostname, **kwargs): def get_domains(): """Return the list of domains configured for ejabberd. """ + app = app_module.App.get('ejabberd') if app.needs_setup(): return [] @@ -197,6 +198,7 @@ def get_domains(): def on_domain_added(sender, domain_type, name='', description='', services=None, **kwargs): """Update ejabberd config after domain name change.""" + app = app_module.App.get('ejabberd') if not name or app.needs_setup(): return @@ -208,6 +210,7 @@ def on_domain_added(sender, domain_type, name='', description='', def set_domains(domains): """Configure ejabberd to have this list of domains.""" + app = app_module.App.get('ejabberd') if not domains or app.needs_setup(): return @@ -220,6 +223,7 @@ def set_domains(domains): def update_turn_configuration(config: TurnConfiguration, managed=True, force=False): """Update ejabberd's STUN/TURN server configuration.""" + app = app_module.App.get('ejabberd') if not force and app.needs_setup(): return diff --git a/plinth/modules/ejabberd/tests/test_turn_config.py b/plinth/modules/ejabberd/tests/test_turn_config.py index b48ddf67d..055a01db5 100644 --- a/plinth/modules/ejabberd/tests/test_turn_config.py +++ b/plinth/modules/ejabberd/tests/test_turn_config.py @@ -5,7 +5,7 @@ Test module for ejabberd STUN/TURN configuration. import pathlib import shutil -from unittest.mock import patch +from unittest.mock import Mock, patch import pytest @@ -59,7 +59,9 @@ def fixture_test_configuration(call_action, conf_file): The module state is patched to be 'up-to-date'. """ with patch('plinth.actions.superuser_run', - call_action), patch('plinth.modules.ejabberd.app') as app: + call_action), patch('plinth.app.App.get') as app_get: + app = Mock() + app_get.return_value = app app.needs_setup.return_value = False yield diff --git a/plinth/modules/email/__init__.py b/plinth/modules/email/__init__.py index c3eb7d48f..71abd5097 100644 --- a/plinth/modules/email/__init__.py +++ b/plinth/modules/email/__init__.py @@ -44,7 +44,6 @@ _description = [ 'uninstalled.') ] -app = None logger = logging.getLogger(__name__) @@ -215,6 +214,7 @@ def _get_first_admin(): def on_domain_added(sender, domain_type, name, description='', services=None, **kwargs): """Handle addition of a new domain.""" + app = plinth.app.App.get('email') if app.needs_setup(): return @@ -223,6 +223,7 @@ def on_domain_added(sender, domain_type, name, description='', services=None, def on_domain_removed(sender, domain_type, name='', **kwargs): """Handle removal of a domain.""" + app = plinth.app.App.get('email') if app.needs_setup(): return diff --git a/plinth/modules/firewall/__init__.py b/plinth/modules/firewall/__init__.py index 8b2dee8a9..e4ddae2fb 100644 --- a/plinth/modules/firewall/__init__.py +++ b/plinth/modules/firewall/__init__.py @@ -31,8 +31,6 @@ _description = [ _port_details = {} -app = None - logger = logging.getLogger(__name__) _DBUS_NAME = 'org.fedoraproject.FirewallD1' diff --git a/plinth/modules/gitweb/__init__.py b/plinth/modules/gitweb/__init__.py index 70fd80743..f6e958377 100644 --- a/plinth/modules/gitweb/__init__.py +++ b/plinth/modules/gitweb/__init__.py @@ -34,8 +34,6 @@ _description = [ 'Git tutorial.') ] -app = None - class GitwebApp(app_module.App): """FreedomBox app for Gitweb.""" @@ -160,7 +158,7 @@ class GitwebBackupRestore(BackupRestore): def restore_post(self, packet): """Update access after restoration of backups.""" super().restore_post(packet) - app.update_service_access() + self.app.update_service_access() def repo_exists(name): diff --git a/plinth/modules/gitweb/tests/test_views.py b/plinth/modules/gitweb/tests/test_views.py index 28a12466c..ce69dc507 100644 --- a/plinth/modules/gitweb/tests/test_views.py +++ b/plinth/modules/gitweb/tests/test_views.py @@ -4,7 +4,7 @@ Tests for gitweb views. """ import json -from unittest.mock import patch +from unittest.mock import Mock, patch import pytest from django import urls @@ -70,7 +70,7 @@ def action_run(*args, **kwargs): def gitweb_patch(): """Patch gitweb.""" with patch('plinth.modules.gitweb.get_repo_list') as get_repo_list, \ - patch('plinth.modules.gitweb.app') as gitweb_app, \ + patch('plinth.app.App.get') as app_get, \ patch('plinth.actions.superuser_run', side_effect=action_run), \ patch('plinth.actions.run', side_effect=action_run): get_repo_list.return_value = [{ @@ -78,7 +78,9 @@ def gitweb_patch(): }, { 'name': EXISTING_REPOS[1]['name'] }] - gitweb_app.update_service_access.return_value = None + app = Mock() + app_get.return_value = app + app.update_service_access.return_value = None yield diff --git a/plinth/modules/gitweb/views.py b/plinth/modules/gitweb/views.py index 2b82eb4b5..6404649be 100644 --- a/plinth/modules/gitweb/views.py +++ b/plinth/modules/gitweb/views.py @@ -12,7 +12,9 @@ from django.urls import reverse_lazy from django.utils.translation import gettext as _ from django.views.generic import FormView -from plinth import actions, views +from plinth import actions +from plinth import app as app_module +from plinth import views from plinth.errors import ActionError from plinth.modules import gitweb @@ -69,7 +71,7 @@ class CreateRepoView(SuccessMessageMixin, FormView): _('An error occurred while creating the repository.'), error_text)) else: - gitweb.app.update_service_access() + app_module.App.get('gitweb').update_service_access() return super().form_valid(form) @@ -115,7 +117,7 @@ class EditRepoView(SuccessMessageMixin, FormView): except ActionError: messages.error(self.request, _('An error occurred during configuration.')) - gitweb.app.update_service_access() + app_module.App.get('gitweb').update_service_access() return super().form_valid(form) @@ -132,6 +134,7 @@ def delete(request, name): else: raise Http404 + app = app_module.App.get('gitweb') if request.method == 'POST': try: gitweb.delete_repo(name) @@ -142,11 +145,11 @@ def delete(request, name): _('Could not delete {name}: {error}').format( name=name, error=error), ) - gitweb.app.update_service_access() + app.update_service_access() return redirect(reverse_lazy('gitweb:index')) return TemplateResponse(request, 'gitweb_delete.html', { - 'title': gitweb.app.info.name, + 'title': app.info.name, 'name': name }) diff --git a/plinth/modules/help/__init__.py b/plinth/modules/help/__init__.py index 26e317e72..0acfa765f 100644 --- a/plinth/modules/help/__init__.py +++ b/plinth/modules/help/__init__.py @@ -14,8 +14,6 @@ from plinth import cfg, menu, web_server logger = logging.getLogger(__name__) -app = None - class HelpApp(app_module.App): """FreedomBox app for showing help.""" diff --git a/plinth/modules/i2p/__init__.py b/plinth/modules/i2p/__init__.py index e70bd3360..aad01f1e1 100644 --- a/plinth/modules/i2p/__init__.py +++ b/plinth/modules/i2p/__init__.py @@ -35,8 +35,6 @@ tunnels_to_manage = { 'Irc2P': 'i2p-irc-freedombox' } -app = None - class I2PApp(app_module.App): """FreedomBox app for I2P.""" diff --git a/plinth/modules/ikiwiki/__init__.py b/plinth/modules/ikiwiki/__init__.py index c9b8edde8..f237a6657 100644 --- a/plinth/modules/ikiwiki/__init__.py +++ b/plinth/modules/ikiwiki/__init__.py @@ -31,8 +31,6 @@ _description = [ users_url=reverse_lazy('users:index')) ] -app = None - class IkiwikiApp(app_module.App): """FreedomBox app for Ikiwiki.""" diff --git a/plinth/modules/ikiwiki/views.py b/plinth/modules/ikiwiki/views.py index 0959bfc04..b7f7c4e20 100644 --- a/plinth/modules/ikiwiki/views.py +++ b/plinth/modules/ikiwiki/views.py @@ -9,20 +9,23 @@ from django.template.response import TemplateResponse from django.urls import reverse_lazy from django.utils.translation import gettext as _ -from plinth import actions, views -from plinth.modules import ikiwiki +from plinth import actions +from plinth import app as app_module +from plinth import views from .forms import IkiwikiCreateForm class IkiwikiAppView(views.AppView): """Serve configuration page.""" + app_id = 'ikiwiki' template_name = 'ikiwiki_configure.html' def get_context_data(self, **kwargs): """Return the context data for rendering the template view.""" - sites = ikiwiki.app.refresh_sites() + app = app_module.App.get('ikiwiki') + sites = app.refresh_sites() sites = [name for name in sites if name != ''] context = super().get_context_data(**kwargs) @@ -34,6 +37,7 @@ def create(request): """Form to create a wiki or blog.""" form = None + app = app_module.App.get('ikiwiki') if request.method == 'POST': form = IkiwikiCreateForm(request.POST, prefix='ikiwiki') if form.is_valid(): @@ -46,16 +50,16 @@ def create(request): form.cleaned_data['admin_name'], form.cleaned_data['admin_password']) - ikiwiki.app.refresh_sites() - if ikiwiki.app.is_enabled(): - ikiwiki.app.set_enabled(True) + app.refresh_sites() + if app.is_enabled(): + app.set_enabled(True) return redirect(reverse_lazy('ikiwiki:index')) else: form = IkiwikiCreateForm(prefix='ikiwiki') return TemplateResponse(request, 'ikiwiki_create.html', { - 'title': ikiwiki.app.info.name, + 'title': app.info.name, 'form': form }) @@ -92,11 +96,12 @@ def delete(request, name): On GET, display a confirmation page. On POST, delete the wiki/blog. """ - title = ikiwiki.app.components['shortcut-ikiwiki-' + name].name + app = app_module.App.get('ikiwiki') + title = app.components['shortcut-ikiwiki-' + name].name if request.method == 'POST': try: actions.superuser_run('ikiwiki', ['delete', '--name', name]) - ikiwiki.app.remove_shortcut(name) + app.remove_shortcut(name) messages.success(request, _('{title} deleted.').format(title=title)) except actions.ActionError as error: @@ -108,6 +113,6 @@ def delete(request, name): return redirect(reverse_lazy('ikiwiki:index')) return TemplateResponse(request, 'ikiwiki_delete.html', { - 'title': ikiwiki.app.info.name, + 'title': app.info.name, 'name': title }) diff --git a/plinth/modules/infinoted/__init__.py b/plinth/modules/infinoted/__init__.py index 2fff6db6c..315b18161 100644 --- a/plinth/modules/infinoted/__init__.py +++ b/plinth/modules/infinoted/__init__.py @@ -26,8 +26,6 @@ _description = [ box_name=_(cfg.box_name)), ] -app = None - class InfinotedApp(app_module.App): """FreedomBox app for infinoted.""" diff --git a/plinth/modules/janus/__init__.py b/plinth/modules/janus/__init__.py index 9fc39be3e..e5e0bf4e3 100644 --- a/plinth/modules/janus/__init__.py +++ b/plinth/modules/janus/__init__.py @@ -27,8 +27,6 @@ _description = [ 'use Janus.'), coturn_url=reverse_lazy('coturn:index')), ] -app = None - class JanusApp(app_module.App): """FreedomBox app for janus.""" diff --git a/plinth/modules/janus/views.py b/plinth/modules/janus/views.py index 849a4da64..a86d1f636 100644 --- a/plinth/modules/janus/views.py +++ b/plinth/modules/janus/views.py @@ -5,7 +5,7 @@ Views for the Janus app. from django.views.generic import TemplateView -from plinth.modules import janus +from plinth import app as app_module class JanusRoomView(TemplateView): @@ -14,7 +14,8 @@ class JanusRoomView(TemplateView): def get_context_data(self, *args, **kwargs): """Add user's TURN server information to view context.""" - config = janus.app.get_component('turn-janus').get_configuration() + app = app_module.App.get('janus') + config = app.get_component('turn-janus').get_configuration() context = super().get_context_data(*args, **kwargs) context['user_turn_config'] = config.to_json() return context diff --git a/plinth/modules/jsxc/__init__.py b/plinth/modules/jsxc/__init__.py index 806fc0c31..45024989d 100644 --- a/plinth/modules/jsxc/__init__.py +++ b/plinth/modules/jsxc/__init__.py @@ -24,8 +24,6 @@ _description = [ logger = logging.getLogger(__name__) -app = None - class JSXCApp(app_module.App): """FreedomBox app for JSXC.""" diff --git a/plinth/modules/letsencrypt/__init__.py b/plinth/modules/letsencrypt/__init__.py index 4fc307aa0..a0ae8fd2b 100644 --- a/plinth/modules/letsencrypt/__init__.py +++ b/plinth/modules/letsencrypt/__init__.py @@ -42,8 +42,6 @@ LIVE_DIRECTORY = '/etc/letsencrypt/live/' CERTIFICATE_CHECK_DELAY = 120 logger = logging.getLogger(__name__) -app = None - class LetsEncryptApp(app_module.App): """FreedomBox app for Let's Encrypt.""" diff --git a/plinth/modules/letsencrypt/views.py b/plinth/modules/letsencrypt/views.py index 0bf67a38e..b9b215b6f 100644 --- a/plinth/modules/letsencrypt/views.py +++ b/plinth/modules/letsencrypt/views.py @@ -12,6 +12,7 @@ from django.urls import reverse_lazy from django.utils.translation import gettext as _ from django.views.decorators.http import require_POST +from plinth import app as app_module from plinth.errors import ActionError from plinth.modules import letsencrypt @@ -21,13 +22,14 @@ logger = logging.getLogger(__name__) def index(request): """Serve configuration page.""" status = letsencrypt.get_status() + app = app_module.App.get('letsencrypt') return TemplateResponse( request, 'letsencrypt.html', { 'app_id': 'letsencrypt', - 'app_info': letsencrypt.app.info, + 'app_info': app.info, 'status': status, 'has_diagnostics': True, - 'is_enabled': letsencrypt.app.is_enabled(), + 'is_enabled': app.is_enabled(), }) diff --git a/plinth/modules/matrixsynapse/__init__.py b/plinth/modules/matrixsynapse/__init__.py index 5349b3e1c..c007994df 100644 --- a/plinth/modules/matrixsynapse/__init__.py +++ b/plinth/modules/matrixsynapse/__init__.py @@ -51,8 +51,6 @@ REGISTRATION_CONF_PATH = CONF_DIR + 'freedombox-registration.yaml' TURN_CONF_PATH = CONF_DIR + 'freedombox-turn.yaml' OVERRIDDEN_TURN_CONF_PATH = CONF_DIR + 'turn.yaml' -app = None - class MatrixSynapseApp(app_module.App): """FreedomBox app for Matrix Synapse.""" @@ -158,6 +156,7 @@ def upgrade(): def setup_domain(domain_name): """Configure a domain name for matrixsynapse.""" + app = app_module.App.get('matrixsynapse') app.get_component('letsencrypt-matrixsynapse').setup_certificates( [domain_name]) actions.superuser_run('matrixsynapse', @@ -212,6 +211,7 @@ def get_public_registration_status() -> bool: def get_certificate_status(): """Return the status of certificate for the configured domain.""" + app = app_module.App.get('matrixsynapse') status = app.get_component('letsencrypt-matrixsynapse').get_status() if not status: return 'no-domains' @@ -222,6 +222,7 @@ def get_certificate_status(): def update_turn_configuration(config: TurnConfiguration, managed=True, force=False): """Update the STUN/TURN server configuration.""" + app = app_module.App.get('matrixsynapse') if not force and app.needs_setup(): return diff --git a/plinth/modules/matrixsynapse/tests/test_turn_config.py b/plinth/modules/matrixsynapse/tests/test_turn_config.py index 28f5bb834..2f48705f0 100644 --- a/plinth/modules/matrixsynapse/tests/test_turn_config.py +++ b/plinth/modules/matrixsynapse/tests/test_turn_config.py @@ -3,7 +3,7 @@ Test module for Matrix Synapse STUN/TURN configuration. """ -from unittest.mock import patch +from unittest.mock import patch, Mock import pytest @@ -51,7 +51,9 @@ def fixture_test_configuration(call_action, managed_turn_conf_file, overridden_turn_conf_file), patch('plinth.modules.matrixsynapse.is_setup', return_value=True), patch('plinth.actions.superuser_run', call_action), - patch('plinth.modules.matrixsynapse.app') as app): + patch('plinth.app.App.get') as app_get): + app = Mock() + app_get.return_value = app app.needs_setup.return_value = False yield diff --git a/plinth/modules/matrixsynapse/views.py b/plinth/modules/matrixsynapse/views.py index 1198d8aa9..3d8ba9a30 100644 --- a/plinth/modules/matrixsynapse/views.py +++ b/plinth/modules/matrixsynapse/views.py @@ -10,6 +10,7 @@ from django.utils.translation import gettext_lazy as _ from django.views.generic import FormView from plinth import actions +from plinth import app as app_module from plinth.forms import DomainSelectionForm from plinth.modules import matrixsynapse, names from plinth.modules.coturn.components import TurnConfiguration @@ -33,9 +34,10 @@ class SetupView(FormView): def get_context_data(self, *args, **kwargs): """Provide context data to the template.""" context = super().get_context_data(**kwargs) + app = app_module.App.get('matrixsynapse') - context['title'] = matrixsynapse.app.info.name - context['app_info'] = matrixsynapse.app.info + context['title'] = app.info.name + context['app_info'] = app.info context['domain_names'] = names.components.DomainName.list_names( 'matrix-synapse-plinth') diff --git a/plinth/modules/mediawiki/__init__.py b/plinth/modules/mediawiki/__init__.py index 7e7608ee8..b2575cb4a 100644 --- a/plinth/modules/mediawiki/__init__.py +++ b/plinth/modules/mediawiki/__init__.py @@ -34,8 +34,6 @@ _description = [ 'logged in can make changes to the content.') ] -app = None - STATIC_CONFIG_FILE = '/etc/mediawiki/FreedomBoxStaticSettings.php' USER_CONFIG_FILE = '/etc/mediawiki/FreedomBoxSettings.php' diff --git a/plinth/modules/mediawiki/views.py b/plinth/modules/mediawiki/views.py index 524c322ab..15e3e7b06 100644 --- a/plinth/modules/mediawiki/views.py +++ b/plinth/modules/mediawiki/views.py @@ -8,7 +8,9 @@ import logging from django.contrib import messages from django.utils.translation import gettext as _ -from plinth import actions, views +from plinth import actions +from plinth import app as app_module +from plinth import views from plinth.errors import ActionError from plinth.modules import mediawiki @@ -87,7 +89,8 @@ class MediaWikiAppView(views.AppView): actions.superuser_run('mediawiki', ['private-mode', 'disable']) messages.success(self.request, _('Private mode disabled')) - shortcut = mediawiki.app.get_component('shortcut-mediawiki') + app = app_module.App.get('mediawiki') + shortcut = app.get_component('shortcut-mediawiki') shortcut.login_required = new_config['enable_private_mode'] if is_changed('default_skin'): diff --git a/plinth/modules/minetest/__init__.py b/plinth/modules/minetest/__init__.py index 822dae826..87f112a1a 100644 --- a/plinth/modules/minetest/__init__.py +++ b/plinth/modules/minetest/__init__.py @@ -42,8 +42,6 @@ _description = [ CONFIG_FILE = '/etc/minetest/minetest.conf' AUG_PATH = '/files' + CONFIG_FILE + '/.anon' -app = None - class MinetestApp(app_module.App): """FreedomBox app for Minetest.""" diff --git a/plinth/modules/minidlna/__init__.py b/plinth/modules/minidlna/__init__.py index f7eaf27aa..8dc6c462b 100644 --- a/plinth/modules/minidlna/__init__.py +++ b/plinth/modules/minidlna/__init__.py @@ -4,8 +4,9 @@ FreedomBox app to configure minidlna. """ from django.utils.translation import gettext_lazy as _ -import plinth.app as app_module -from plinth import actions, frontpage, menu +from plinth import actions +from plinth import app as app_module +from plinth import frontpage, menu from plinth.daemon import Daemon from plinth.modules.apache.components import Webserver from plinth.modules.backups.components import BackupRestore @@ -27,8 +28,6 @@ _description = [ 'such as PS3 and Xbox 360) or applications such as totem and Kodi.') ] -app = None - class MiniDLNAApp(app_module.App): """Freedombox app managing miniDlna""" diff --git a/plinth/modules/mumble/__init__.py b/plinth/modules/mumble/__init__.py index 9eb4a1332..b18ce5d4d 100644 --- a/plinth/modules/mumble/__init__.py +++ b/plinth/modules/mumble/__init__.py @@ -29,8 +29,6 @@ _description = [ 'from your desktop and mobile devices are available.') ] -app = None - class MumbleApp(app_module.App): """FreedomBox app for Mumble.""" @@ -100,7 +98,7 @@ class MumbleApp(app_module.App): if not old_version: self.enable() - app.get_component('letsencrypt-mumble').setup_certificates() + self.get_component('letsencrypt-mumble').setup_certificates() def force_upgrade(self, packages): """Force upgrade mumble-server to resolve conffile prompts.""" diff --git a/plinth/modules/mumble/views.py b/plinth/modules/mumble/views.py index d7406b61a..a6c96dabb 100644 --- a/plinth/modules/mumble/views.py +++ b/plinth/modules/mumble/views.py @@ -6,6 +6,7 @@ Views for mumble app. from django.contrib import messages from django.utils.translation import gettext_lazy as _ +from plinth import app as app_module from plinth.modules import mumble from plinth.modules.mumble.forms import MumbleForm from plinth.views import AppView @@ -31,7 +32,8 @@ class MumbleAppView(AppView): if mumble.get_domain() != new_config['domain']: privileged.set_domain(new_config['domain']) - mumble.app.get_component('letsencrypt-mumble').setup_certificates() + app = app_module.App.get('mumble') + app.get_component('letsencrypt-mumble').setup_certificates() messages.success(self.request, _('Configuration updated')) password = new_config.get('super_user_password') diff --git a/plinth/modules/names/__init__.py b/plinth/modules/names/__init__.py index 948486b80..07c9e06e7 100644 --- a/plinth/modules/names/__init__.py +++ b/plinth/modules/names/__init__.py @@ -26,8 +26,6 @@ _description = [ 'connections through the given name.'), box_name=(cfg.box_name)) ] -app = None - class NamesApp(app_module.App): """FreedomBox app for names.""" diff --git a/plinth/modules/names/views.py b/plinth/modules/names/views.py index b043b5ca3..4c0cb51d6 100644 --- a/plinth/modules/names/views.py +++ b/plinth/modules/names/views.py @@ -5,7 +5,7 @@ FreedomBox app for name services. from django.template.response import TemplateResponse -from plinth.modules import names +from plinth import app as app_module from . import components @@ -15,7 +15,7 @@ def index(request): status = get_status() return TemplateResponse(request, 'names.html', { - 'app_info': names.app.info, + 'app_info': app_module.App.get('names').info, 'status': status }) diff --git a/plinth/modules/networks/__init__.py b/plinth/modules/networks/__init__.py index eb345c85f..df6485ae3 100644 --- a/plinth/modules/networks/__init__.py +++ b/plinth/modules/networks/__init__.py @@ -40,8 +40,6 @@ _description = [ logger = Logger(__name__) -app = None - class NetworksApp(app_module.App): """FreedomBox app for Networks.""" diff --git a/plinth/modules/networks/views.py b/plinth/modules/networks/views.py index 4dbe18bb8..c799dadb0 100644 --- a/plinth/modules/networks/views.py +++ b/plinth/modules/networks/views.py @@ -12,6 +12,7 @@ from django.utils.translation import gettext_lazy from django.views.decorators.http import require_POST from django.views.generic.edit import FormView +from plinth import app as app_module from plinth import network from plinth.modules import first_boot, networks @@ -123,7 +124,7 @@ def index(request): return TemplateResponse( request, 'networks_configuration.html', { 'app_id': 'networks', - 'app_info': networks.app.info, + 'app_info': app_module.App.get('networks').info, 'title': _('Network Connections'), 'has_diagnostics': True, 'is_enabled': True, diff --git a/plinth/modules/openvpn/__init__.py b/plinth/modules/openvpn/__init__.py index 7bad2f710..4ec97d813 100644 --- a/plinth/modules/openvpn/__init__.py +++ b/plinth/modules/openvpn/__init__.py @@ -31,8 +31,6 @@ _description = [ 'for added security and anonymity.'), box_name=_(cfg.box_name)) ] -app = None - SERVER_CONFIGURATION_FILE = '/etc/openvpn/server/freedombox.conf' diff --git a/plinth/modules/openvpn/views.py b/plinth/modules/openvpn/views.py index 7ebdcfa43..903093bd6 100644 --- a/plinth/modules/openvpn/views.py +++ b/plinth/modules/openvpn/views.py @@ -10,6 +10,7 @@ from django.shortcuts import redirect from django.views.decorators.http import require_POST from plinth import actions +from plinth import app as app_module from plinth.modules import config, openvpn from plinth.views import AppView @@ -37,7 +38,7 @@ def setup(_): if not openvpn.is_setup(): actions.superuser_run('openvpn', ['setup'], run_in_background=True) - openvpn.app.enable() + app_module.App.get('openvpn').enable() return redirect('openvpn:index') diff --git a/plinth/modules/pagekite/__init__.py b/plinth/modules/pagekite/__init__.py index f0a45354c..d959a0286 100644 --- a/plinth/modules/pagekite/__init__.py +++ b/plinth/modules/pagekite/__init__.py @@ -42,8 +42,6 @@ _description = [ box_name=_(cfg.box_name)) ] -app = None - class PagekiteApp(app_module.App): """FreedomBox app for Pagekite.""" diff --git a/plinth/modules/pagekite/utils.py b/plinth/modules/pagekite/utils.py index f551beea9..8b00cf7b6 100644 --- a/plinth/modules/pagekite/utils.py +++ b/plinth/modules/pagekite/utils.py @@ -7,6 +7,7 @@ import os from django.utils.translation import gettext_lazy as _ from plinth import actions +from plinth import app as app_module from plinth.signals import domain_added, domain_removed LOGGER = logging.getLogger(__name__) @@ -172,8 +173,7 @@ def update_names_module(is_enabled=None): if is_enabled is False: return - from plinth.modules.pagekite import app - if is_enabled is None and not app.is_enabled(): + if is_enabled is None and not app_module.App.get('pagekite').is_enabled(): return config = get_config() diff --git a/plinth/modules/performance/__init__.py b/plinth/modules/performance/__init__.py index 1dbdbe71f..6fa9f5cf0 100644 --- a/plinth/modules/performance/__init__.py +++ b/plinth/modules/performance/__init__.py @@ -24,8 +24,6 @@ _description = [ 'viewed using the Cockpit app.'), ] -app = None - class PerformanceApp(app_module.App): """FreedomBox app for Performance.""" diff --git a/plinth/modules/power/__init__.py b/plinth/modules/power/__init__.py index 489fc580d..8137456ee 100644 --- a/plinth/modules/power/__init__.py +++ b/plinth/modules/power/__init__.py @@ -13,8 +13,6 @@ from . import manifest _description = [_('Restart or shut down the system.')] -app = None - class PowerApp(app_module.App): """FreedomBox app for power controls.""" diff --git a/plinth/modules/power/views.py b/plinth/modules/power/views.py index fad662eca..9b59380a1 100644 --- a/plinth/modules/power/views.py +++ b/plinth/modules/power/views.py @@ -8,16 +8,18 @@ from django.shortcuts import redirect from django.template.response import TemplateResponse from django.urls import reverse -from plinth import actions, package -from plinth.modules import power +from plinth import actions +from plinth import app as app_module +from plinth import package def index(request): """Serve power controls page.""" + app = app_module.App.get('power') return TemplateResponse( request, 'power.html', { - 'title': power.app.info.name, - 'app_info': power.app.info, + 'title': app.info.name, + 'app_info': app.info, 'pkg_manager_is_busy': package.is_package_manager_busy() }) @@ -30,12 +32,13 @@ def restart(request): actions.superuser_run('power', ['restart'], run_in_background=True) return redirect(reverse('apps')) + app = app_module.App.get('power') form = Form(prefix='power') return TemplateResponse( request, 'power_restart.html', { - 'title': power.app.info.name, + 'title': app.info.name, 'form': form, - 'manual_page': power.app.info.manual_page, + 'manual_page': app.info.manual_page, 'pkg_manager_is_busy': package.is_package_manager_busy() }) @@ -48,11 +51,12 @@ def shutdown(request): actions.superuser_run('power', ['shutdown'], run_in_background=True) return redirect(reverse('apps')) + app = app_module.App.get('power') form = Form(prefix='power') return TemplateResponse( request, 'power_shutdown.html', { - 'title': power.app.info.name, + 'title': app.info.name, 'form': form, - 'manual_page': power.app.info.manual_page, + 'manual_page': app.info.manual_page, 'pkg_manager_is_busy': package.is_package_manager_busy() }) diff --git a/plinth/modules/privoxy/__init__.py b/plinth/modules/privoxy/__init__.py index ad7e590e9..75dc3f6c6 100644 --- a/plinth/modules/privoxy/__init__.py +++ b/plinth/modules/privoxy/__init__.py @@ -35,8 +35,6 @@ _description = [ box_name=_(cfg.box_name)), ] -app = None - class PrivoxyApp(app_module.App): """FreedomBox app for Privoxy.""" diff --git a/plinth/modules/quassel/__init__.py b/plinth/modules/quassel/__init__.py index fdd6026b4..0405e9cb9 100644 --- a/plinth/modules/quassel/__init__.py +++ b/plinth/modules/quassel/__init__.py @@ -38,8 +38,6 @@ _description = [ 'are available.'), ] -app = None - class QuasselApp(app_module.App): """FreedomBox app for Quassel.""" diff --git a/plinth/modules/quassel/views.py b/plinth/modules/quassel/views.py index 90d2ca56b..8636cfdbb 100644 --- a/plinth/modules/quassel/views.py +++ b/plinth/modules/quassel/views.py @@ -3,6 +3,7 @@ from django.contrib import messages from django.utils.translation import gettext_lazy as _ +from plinth import app as app_module from plinth.forms import TLSDomainForm from plinth.modules import quassel from plinth.views import AppView @@ -23,8 +24,8 @@ class QuasselAppView(AppView): data = form.cleaned_data if quassel.get_domain() != data['domain']: quassel.set_domain(data['domain']) - quassel.app.get_component( - 'letsencrypt-quassel').setup_certificates() + app = app_module.App.get('quassel') + app.get_component('letsencrypt-quassel').setup_certificates() messages.success(self.request, _('Configuration updated')) return super().form_valid(form) diff --git a/plinth/modules/radicale/__init__.py b/plinth/modules/radicale/__init__.py index f55100f67..118f60164 100644 --- a/plinth/modules/radicale/__init__.py +++ b/plinth/modules/radicale/__init__.py @@ -37,8 +37,6 @@ logger = logging.getLogger(__name__) CONFIG_FILE = '/etc/radicale/config' -app = None - class RadicaleApp(app_module.App): """FreedomBox app for Radicale.""" diff --git a/plinth/modules/roundcube/__init__.py b/plinth/modules/roundcube/__init__.py index e29fbf4d8..86e6ee0c2 100644 --- a/plinth/modules/roundcube/__init__.py +++ b/plinth/modules/roundcube/__init__.py @@ -33,8 +33,6 @@ _description = [ '>https://www.google.com/settings/security/lesssecureapps).'), ] -app = None - class RoundcubeApp(app_module.App): """FreedomBox app for Roundcube.""" diff --git a/plinth/modules/rssbridge/__init__.py b/plinth/modules/rssbridge/__init__.py index 5a9ff331d..460d833f8 100644 --- a/plinth/modules/rssbridge/__init__.py +++ b/plinth/modules/rssbridge/__init__.py @@ -30,8 +30,6 @@ _description = [ ttrss_url=reverse_lazy('ttrss:index'), box_name=cfg.box_name), ] -app = None - class RSSBridgeApp(app_module.App): """FreedomBox app for RSS-Bridge.""" diff --git a/plinth/modules/samba/__init__.py b/plinth/modules/samba/__init__.py index cd72af27d..3730da2fd 100644 --- a/plinth/modules/samba/__init__.py +++ b/plinth/modules/samba/__init__.py @@ -39,8 +39,6 @@ _description = [ 'own private space.'), ] -app = None - class SambaApp(app_module.App): """FreedomBox app for Samba file sharing.""" diff --git a/plinth/modules/searx/__init__.py b/plinth/modules/searx/__init__.py index 1c685ecd4..27b8fe9cb 100644 --- a/plinth/modules/searx/__init__.py +++ b/plinth/modules/searx/__init__.py @@ -25,8 +25,6 @@ _description = [ 'It stores no cookies by default.') ] -app = None - class SearxApp(app_module.App): """FreedomBox app for Searx.""" @@ -131,6 +129,7 @@ def is_public_access_enabled(): def enable_public_access(): """Allow Searx app to be accessed by anyone with access.""" actions.superuser_run('searx', ['enable-public-access']) + app = app_module.App.get('searx') app.get_component('webserver-searx-auth').disable() app.set_shortcut_login_required(False) @@ -138,5 +137,6 @@ def enable_public_access(): def disable_public_access(): """Allow Searx app to be accessed by logged-in users only.""" actions.superuser_run('searx', ['disable-public-access']) + app = app_module.App.get('searx') app.get_component('webserver-searx-auth').enable() app.set_shortcut_login_required(True) diff --git a/plinth/modules/searx/views.py b/plinth/modules/searx/views.py index 3a8e8f8ea..dbe80e658 100644 --- a/plinth/modules/searx/views.py +++ b/plinth/modules/searx/views.py @@ -6,7 +6,9 @@ Django views for Searx. from django.contrib import messages from django.utils.translation import gettext as _ -from plinth import actions, views +from plinth import actions +from plinth import app as app_module +from plinth import views from plinth.errors import ActionError from plinth.modules import searx @@ -23,7 +25,7 @@ class SearxAppView(views.AppView): initial = super().get_initial() initial['safe_search'] = searx.get_safe_search_setting() initial['public_access'] = searx.is_public_access_enabled() and \ - searx.app.is_enabled() + app_module.App.get('searx').is_enabled() return initial def form_valid(self, form): diff --git a/plinth/modules/security/__init__.py b/plinth/modules/security/__init__.py index dcfe24007..915afd98b 100644 --- a/plinth/modules/security/__init__.py +++ b/plinth/modules/security/__init__.py @@ -24,8 +24,6 @@ ACCESS_CONF_SNIPPET = '-:ALL EXCEPT root fbx plinth (admin) (sudo):ALL' OLD_ACCESS_CONF_SNIPPET = '-:ALL EXCEPT root fbx (admin) (sudo):ALL' ACCESS_CONF_SNIPPETS = [OLD_ACCESS_CONF_SNIPPET, ACCESS_CONF_SNIPPET] -app = None - class SecurityApp(app_module.App): """FreedomBox app for security.""" diff --git a/plinth/modules/security/views.py b/plinth/modules/security/views.py index d284098df..3c21eb631 100644 --- a/plinth/modules/security/views.py +++ b/plinth/modules/security/views.py @@ -8,6 +8,7 @@ from django.template.response import TemplateResponse from django.utils.translation import gettext as _ from plinth import action_utils, actions +from plinth import app as app_module from plinth.modules import security from plinth.modules.upgrades import is_backports_requested @@ -31,7 +32,7 @@ def index(request): return TemplateResponse( request, 'security.html', { - 'app_info': security.app.info, + 'app_info': app_module.App.get('security').info, 'form': form, 'is_backports_requested': is_backports_requested(), }) diff --git a/plinth/modules/shaarli/__init__.py b/plinth/modules/shaarli/__init__.py index 585d3511c..ed7f054f2 100644 --- a/plinth/modules/shaarli/__init__.py +++ b/plinth/modules/shaarli/__init__.py @@ -20,8 +20,6 @@ _description = [ 'need to setup on the initial visit.'), ] -app = None - class ShaarliApp(app_module.App): """FreedomBox app for Shaarli.""" diff --git a/plinth/modules/shadowsocks/__init__.py b/plinth/modules/shadowsocks/__init__.py index fd1b68af6..b91cb6e47 100644 --- a/plinth/modules/shadowsocks/__init__.py +++ b/plinth/modules/shadowsocks/__init__.py @@ -31,8 +31,6 @@ _description = [ 'device, browser or application to http://freedombox_address:1080/') ] -app = None - class ShadowsocksApp(app_module.App): """FreedomBox app for Shadowsocks.""" diff --git a/plinth/modules/sharing/__init__.py b/plinth/modules/sharing/__init__.py index 94ebf1635..c716b13b5 100644 --- a/plinth/modules/sharing/__init__.py +++ b/plinth/modules/sharing/__init__.py @@ -22,8 +22,6 @@ _description = [ box_name=_(cfg.box_name)) ] -app = None - class SharingApp(app_module.App): """FreedomBox app for sharing files.""" diff --git a/plinth/modules/sharing/views.py b/plinth/modules/sharing/views.py index 1bca8f15f..26c0b75b8 100644 --- a/plinth/modules/sharing/views.py +++ b/plinth/modules/sharing/views.py @@ -12,6 +12,7 @@ from django.utils.translation import gettext_lazy as _ from django.views.decorators.http import require_POST from django.views.generic import FormView, TemplateView +from plinth import app as app_module from plinth.modules import sharing from .forms import AddShareForm @@ -24,8 +25,9 @@ class IndexView(TemplateView): def get_context_data(self, **kwargs): """Return additional context for rendering the template.""" context = super().get_context_data(**kwargs) - context['title'] = sharing.app.info.name - context['app_info'] = sharing.app.info + app = app_module.App.get('sharing') + context['title'] = app.info.name + context['app_info'] = app.info context['shares'] = sharing.list_shares() return context diff --git a/plinth/modules/snapshot/__init__.py b/plinth/modules/snapshot/__init__.py index 2396e2c7a..015bac1f5 100644 --- a/plinth/modules/snapshot/__init__.py +++ b/plinth/modules/snapshot/__init__.py @@ -36,8 +36,6 @@ DEFAULT_FILE = '/etc/default/snapper' fs_types_supported = ['btrfs'] -app = None - class SnapshotApp(app_module.App): """FreedomBox app for snapshots.""" diff --git a/plinth/modules/snapshot/views.py b/plinth/modules/snapshot/views.py index 70a3ce678..960383b9f 100644 --- a/plinth/modules/snapshot/views.py +++ b/plinth/modules/snapshot/views.py @@ -15,6 +15,7 @@ from django.utils.translation import gettext as _ from django.utils.translation import gettext_lazy from plinth import actions +from plinth import app as app_module from plinth.errors import ActionError from plinth.modules import snapshot as snapshot_module from plinth.modules import storage @@ -43,9 +44,10 @@ subsubmenu = [ def not_supported_view(request): """Show that snapshots are not supported on the system.""" + app = app_module.App.get('snapshot') template_data = { - 'app_info': snapshot_module.app.info, - 'title': snapshot_module.app.info.name, + 'app_info': app.info, + 'title': app.info.name, 'fs_type': storage.get_filesystem_type(), 'fs_types_supported': snapshot_module.fs_types_supported, } @@ -68,10 +70,11 @@ def index(request): else: form = SnapshotForm(initial=status) + app = app_module.App.get('snapshot') return TemplateResponse( request, 'snapshot.html', { - 'app_info': snapshot_module.app.info, - 'title': snapshot_module.app.info.name, + 'app_info': app.info, + 'title': app.info.name, 'subsubmenu': subsubmenu, 'form': form }) @@ -103,10 +106,11 @@ def manage(request): if not snapshot['is_default'] and not snapshot['is_active'] ]) + app = app_module.App.get('snapshot') return TemplateResponse( request, 'snapshot_manage.html', { - 'title': snapshot_module.app.info.name, - 'app_info': snapshot_module.app.info, + 'title': app.info.name, + 'app_info': app.info, 'snapshots': snapshots, 'has_deletable_snapshots': has_deletable_snapshots, 'subsubmenu': subsubmenu, diff --git a/plinth/modules/ssh/__init__.py b/plinth/modules/ssh/__init__.py index bcafea98e..13e358aa6 100644 --- a/plinth/modules/ssh/__init__.py +++ b/plinth/modules/ssh/__init__.py @@ -26,8 +26,6 @@ _description = [ 'using such connections.') ] -app = None - class SSHApp(app_module.App): """FreedomBox app for SSH.""" diff --git a/plinth/modules/sso/__init__.py b/plinth/modules/sso/__init__.py index a70b05937..8a3aeddb5 100644 --- a/plinth/modules/sso/__init__.py +++ b/plinth/modules/sso/__init__.py @@ -9,8 +9,6 @@ from plinth import actions from plinth import app as app_module from plinth.package import Packages -app = None - class SSOApp(app_module.App): """FreedomBox app for single sign on.""" diff --git a/plinth/modules/storage/__init__.py b/plinth/modules/storage/__init__.py index bf138f952..a823ccba6 100644 --- a/plinth/modules/storage/__init__.py +++ b/plinth/modules/storage/__init__.py @@ -31,8 +31,6 @@ _description = [ logger = logging.getLogger(__name__) -app = None - class StorageApp(app_module.App): """FreedomBox app for storage.""" diff --git a/plinth/modules/syncthing/__init__.py b/plinth/modules/syncthing/__init__.py index c6a5afb49..2f0a9eb88 100644 --- a/plinth/modules/syncthing/__init__.py +++ b/plinth/modules/syncthing/__init__.py @@ -37,8 +37,6 @@ _description = [ SYSTEM_USER = 'syncthing' -app = None - class SyncthingApp(app_module.App): """FreedomBox app for Syncthing.""" diff --git a/plinth/modules/tor/__init__.py b/plinth/modules/tor/__init__.py index ecded31f8..8ab11904a 100644 --- a/plinth/modules/tor/__init__.py +++ b/plinth/modules/tor/__init__.py @@ -35,8 +35,6 @@ _description = [ 'networks on TCP port 9050.'), box_name=_(cfg.box_name)) ] -app = None - class TorApp(app_module.App): """FreedomBox app for Tor.""" @@ -97,7 +95,7 @@ class TorApp(app_module.App): def post_init(self): """Perform post initialization operations.""" # Register hidden service name with Name Services module. - if (not app.needs_setup() and self.is_enabled() + if (not self.needs_setup() and self.is_enabled() and app_is_running(self)): status = utils.get_status(initialized=False) hostname = status['hs_hostname'] diff --git a/plinth/modules/tor/tests/test_tor.py b/plinth/modules/tor/tests/test_tor.py index 7efff89a8..de0939a9a 100644 --- a/plinth/modules/tor/tests/test_tor.py +++ b/plinth/modules/tor/tests/test_tor.py @@ -13,6 +13,7 @@ from plinth.modules.tor import forms, utils class TestTor: """Test cases for testing the Tor module.""" + @staticmethod @pytest.mark.usefixtures('needs_root') def test_is_apt_transport_tor_enabled(): @@ -22,9 +23,9 @@ class TestTor: utils.is_apt_transport_tor_enabled() @staticmethod - @patch('plinth.modules.tor.app') + @patch('plinth.app.App.get') @pytest.mark.usefixtures('needs_root', 'load_cfg') - def test_get_status(_app): + def test_get_status(_app_get): """Test that get_status does not raise any unhandled exceptions. This should work regardless of whether tor is installed, or @@ -35,6 +36,7 @@ class TestTor: class TestTorForm: """Test whether Tor configration form works.""" + @staticmethod def test_bridge_validator(): """Test upstream bridges' form field validator.""" diff --git a/plinth/modules/tor/utils.py b/plinth/modules/tor/utils.py index 292d2925c..935e48a85 100644 --- a/plinth/modules/tor/utils.py +++ b/plinth/modules/tor/utils.py @@ -10,8 +10,8 @@ import json import augeas from plinth import actions +from plinth import app as app_module from plinth.daemon import app_is_running -from plinth.modules import tor from plinth.modules.names.components import DomainName APT_SOURCES_URI_PATHS = ('/files/etc/apt/sources.list/*/uri', @@ -42,9 +42,10 @@ def get_status(initialized=True): or status['bridge_relay_enabled'] } + app = app_module.App.get('tor') return { - 'enabled': tor.app.is_enabled() if initialized else False, - 'is_running': app_is_running(tor.app) if initialized else False, + 'enabled': app.is_enabled() if initialized else False, + 'is_running': app_is_running(app) if initialized else False, 'use_upstream_bridges': status['use_upstream_bridges'], 'upstream_bridges': status['upstream_bridges'], 'relay_enabled': status['relay_enabled'], diff --git a/plinth/modules/tor/views.py b/plinth/modules/tor/views.py index 2d9871af2..f4c42d32d 100644 --- a/plinth/modules/tor/views.py +++ b/plinth/modules/tor/views.py @@ -7,6 +7,7 @@ from django.template.response import TemplateResponse from django.utils.translation import gettext as _ from plinth import actions +from plinth import app as app_module from plinth.errors import ActionError from plinth.modules import tor from plinth.modules.firewall.components import (Firewall, @@ -36,18 +37,19 @@ def index(request): else: form = TorForm(initial=status, prefix='tor') + app = app_module.App.get('tor') return TemplateResponse( request, 'tor.html', { 'app_id': 'tor', - 'app_info': tor.app.info, + 'app_info': app.info, 'status': status, 'config_running': bool(config_process), 'form': form, - 'firewall': tor.app.get_components_of_type(Firewall), + 'firewall': app.get_components_of_type(Firewall), 'has_diagnostics': True, 'is_enabled': status['enabled'], 'is_running': status['is_running'], - 'port_forwarding_info': get_port_forwarding_info(tor.app), + 'port_forwarding_info': get_port_forwarding_info(app), 'refresh_page_sec': 3 if bool(config_process) else None, }) @@ -116,10 +118,11 @@ def __apply_changes(request, old_status, new_status): arg_value = 'enable' if new_status['enabled'] else 'disable' arguments.extend(['--service', arg_value]) # XXX: Perform app enable/disable within the background process + app = app_module.App.get('tor') if new_status['enabled']: - tor.app.enable() + app.enable() else: - tor.app.disable() + app.disable() config_process = actions.superuser_run('tor', ['configure'] + arguments, diff --git a/plinth/modules/transmission/__init__.py b/plinth/modules/transmission/__init__.py index d778ac40c..10208cad3 100644 --- a/plinth/modules/transmission/__init__.py +++ b/plinth/modules/transmission/__init__.py @@ -42,8 +42,6 @@ _description = [ sharing_url=reverse_lazy('sharing:index')) ] -app = None - SYSTEM_USER = 'debian-transmission' diff --git a/plinth/modules/ttrss/__init__.py b/plinth/modules/ttrss/__init__.py index 78c5ab4cd..f17aca2e1 100644 --- a/plinth/modules/ttrss/__init__.py +++ b/plinth/modules/ttrss/__init__.py @@ -33,8 +33,6 @@ _description = [ 'the URL /tt-rss-app for connecting.')) ] -app = None - class TTRSSApp(app_module.App): """FreedomBox app for TT-RSS.""" diff --git a/plinth/modules/upgrades/__init__.py b/plinth/modules/upgrades/__init__.py index a73bfafb2..9eba07745 100644 --- a/plinth/modules/upgrades/__init__.py +++ b/plinth/modules/upgrades/__init__.py @@ -44,8 +44,6 @@ _description = [ 'unavailable briefly.') ] -app = None - BACKPORTS_REQUESTED_KEY = 'upgrades_backports_requested' DIST_UPGRADE_ENABLED_KEY = 'upgrades_dist_upgrade_enabled' diff --git a/plinth/modules/users/__init__.py b/plinth/modules/users/__init__.py index a03ff3e19..4f4d18784 100644 --- a/plinth/modules/users/__init__.py +++ b/plinth/modules/users/__init__.py @@ -37,8 +37,6 @@ _description = [ box_name=_(cfg.box_name)) ] -app = None - class UsersApp(app_module.App): """FreedomBox app for users and groups management.""" diff --git a/plinth/modules/wireguard/__init__.py b/plinth/modules/wireguard/__init__.py index 9b78f114d..0dc632196 100644 --- a/plinth/modules/wireguard/__init__.py +++ b/plinth/modules/wireguard/__init__.py @@ -29,8 +29,6 @@ _description = [ box_name=_(cfg.box_name)) ] -app = None - SERVER_INTERFACE = 'wg0' diff --git a/plinth/modules/wordpress/__init__.py b/plinth/modules/wordpress/__init__.py index f55c205c0..ae1edd000 100644 --- a/plinth/modules/wordpress/__init__.py +++ b/plinth/modules/wordpress/__init__.py @@ -40,8 +40,6 @@ _description = [ 'be installed and upgraded at your own risk.'), ] -app = None - class WordPressApp(app_module.App): """FreedomBox app for WordPress.""" diff --git a/plinth/modules/zoph/__init__.py b/plinth/modules/zoph/__init__.py index 0e3cc898f..71ac501a1 100644 --- a/plinth/modules/zoph/__init__.py +++ b/plinth/modules/zoph/__init__.py @@ -40,8 +40,6 @@ _description = [ box_name=_(cfg.box_name)) ] -app = None - class ZophApp(app_module.App): """FreedomBox app for Zoph.""" diff --git a/plinth/modules/zoph/views.py b/plinth/modules/zoph/views.py index bb7ddc972..485fa30b5 100644 --- a/plinth/modules/zoph/views.py +++ b/plinth/modules/zoph/views.py @@ -12,6 +12,7 @@ from django.urls import reverse_lazy from django.utils.translation import gettext as _ from django.views.generic import TemplateView +from plinth import app as app_module from plinth import views from plinth.errors import ActionError from plinth.modules import zoph @@ -29,8 +30,9 @@ class SetupView(TemplateView): def get_context_data(self, *args, **kwargs): """Provide context data to the template.""" context = super().get_context_data(**kwargs) - context['title'] = zoph.app.info.name - context['app_info'] = zoph.app.info + app = app_module.App.get('zoph') + context['title'] = app.info.name + context['app_info'] = app.info return context def post(self, _request, *args, **kwargs):