From 4100d363814abc3793b897f9d09477b50b931bad Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Wed, 22 May 2019 15:47:00 -0700 Subject: [PATCH] Introduce webserver component for managing Apache configuration Signed-off-by: Sunil Mohan Adapa Reviewed-by: James Valleroy --- actions/cockpit | 6 +- actions/coquelicot | 3 +- actions/deluge | 4 - actions/diaspora | 18 ++--- actions/ejabberd | 12 +-- actions/i2p | 2 - actions/ikiwiki | 37 ++------- actions/matrixsynapse | 2 - actions/mediawiki | 4 - actions/mldonkey | 2 - actions/radicale | 3 - actions/repro | 2 - actions/roundcube | 14 ---- actions/searx | 8 -- actions/shaarli | 60 --------------- actions/syncthing | 11 ++- actions/tahoe-lafs | 6 +- actions/transmission | 2 - actions/ttrss | 19 ++--- plinth/app.py | 2 +- plinth/modules/apache/components.py | 60 +++++++++++++++ .../modules/apache/tests/test_components.py | 77 +++++++++++++++++++ plinth/modules/cockpit/__init__.py | 6 +- plinth/modules/coquelicot/__init__.py | 6 +- plinth/modules/deluge/__init__.py | 7 +- plinth/modules/diaspora/__init__.py | 6 +- plinth/modules/ejabberd/__init__.py | 4 + plinth/modules/i2p/__init__.py | 7 +- plinth/modules/ikiwiki/__init__.py | 8 +- plinth/modules/matrixsynapse/__init__.py | 8 +- plinth/modules/mediawiki/__init__.py | 10 ++- plinth/modules/mldonkey/__init__.py | 9 ++- plinth/modules/radicale/__init__.py | 39 ++++++---- plinth/modules/repro/__init__.py | 4 + plinth/modules/roundcube/__init__.py | 8 +- plinth/modules/searx/__init__.py | 26 ++++++- plinth/modules/shaarli/__init__.py | 9 ++- plinth/modules/syncthing/__init__.py | 6 +- plinth/modules/tahoe/__init__.py | 6 +- plinth/modules/transmission/__init__.py | 6 +- plinth/modules/ttrss/__init__.py | 7 +- 41 files changed, 312 insertions(+), 224 deletions(-) delete mode 100755 actions/shaarli create mode 100644 plinth/modules/apache/components.py create mode 100644 plinth/modules/apache/tests/test_components.py diff --git a/actions/cockpit b/actions/cockpit index d117323cc..b900eb454 100755 --- a/actions/cockpit +++ b/actions/cockpit @@ -22,6 +22,7 @@ Configuration helper for Cockpit. import argparse import augeas + from plinth import action_utils CONFIG_FILE = '/etc/cockpit/cockpit.conf' @@ -63,21 +64,16 @@ def subcommand_setup(arguments): aug.set('/files' + CONFIG_FILE + '/WebService/UrlRoot', '/_cockpit/') aug.save() - with action_utils.WebserverChange() as webserver_change: - webserver_change.enable('cockpit-freedombox') - action_utils.service_restart('cockpit.socket') def subcommand_enable(_): """Enable web configuration and reload.""" action_utils.service_enable('cockpit.socket') - action_utils.webserver_enable('cockpit-freedombox') def subcommand_disable(_): """Disable web configuration and reload.""" - action_utils.webserver_disable('cockpit-freedombox') action_utils.service_disable('cockpit.socket') diff --git a/actions/coquelicot b/actions/coquelicot index 8f8fe64eb..7f1fca3eb 100755 --- a/actions/coquelicot +++ b/actions/coquelicot @@ -26,6 +26,7 @@ import os import sys import yaml + from plinth import action_utils SETTINGS_FILE = '/etc/coquelicot/settings.yml' @@ -72,12 +73,10 @@ def subcommand_setup(_): def subcommand_enable(_): """Enable web configuration and reload.""" action_utils.service_enable('coquelicot') - action_utils.webserver_enable('coquelicot-freedombox') def subcommand_disable(_): """Disable web configuration and reload.""" - action_utils.webserver_disable('coquelicot-freedombox') action_utils.service_disable('coquelicot') diff --git a/actions/deluge b/actions/deluge index b5d88a3ff..9b7885d57 100755 --- a/actions/deluge +++ b/actions/deluge @@ -15,7 +15,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # - """ Configuration helper for BitTorrent web client. """ @@ -26,7 +25,6 @@ import subprocess from plinth import action_utils - SYSTEMD_SERVICE_PATH = '/etc/systemd/system/deluge-web.service' SYSTEMD_SERVICE = ''' # @@ -65,12 +63,10 @@ def subcommand_enable(_): """Enable deluge-web site and start deluge-web.""" setup() action_utils.service_enable('deluge-web') - action_utils.webserver_enable('deluge-plinth') def subcommand_disable(_): """Disable deluge-web site and stop deluge-web.""" - action_utils.webserver_disable('deluge-plinth') action_utils.service_disable('deluge-web') diff --git a/actions/diaspora b/actions/diaspora index c8cd46ba1..79321735a 100755 --- a/actions/diaspora +++ b/actions/diaspora @@ -20,9 +20,10 @@ Configuration helper for diaspora* pod. """ import argparse -import augeas import subprocess +import augeas + from plinth import action_utils from plinth.modules import diaspora @@ -46,10 +47,10 @@ def parse_arguments(): subparsers.add_parser('start-diaspora', help='Start diaspora* service') subparsers.add_parser( 'disable-ssl', help="Disable SSL on the diaspora* application server") - setup = subparsers.add_parser( - 'setup', help='Set Domain name for diaspora*') - setup.add_argument( - '--domain-name', help='The domain name that will be used by diaspora*') + setup = subparsers.add_parser('setup', + help='Set Domain name for diaspora*') + setup.add_argument('--domain-name', + help='The domain name that will be used by diaspora*') return parser.parse_args() @@ -61,7 +62,6 @@ def subcommand_setup(arguments): dnf.write(domain_name) set_domain_name(domain_name) uncomment_user_registrations() - action_utils.webserver_enable('diaspora-plinth') def set_domain_name(domain_name): @@ -71,8 +71,8 @@ def set_domain_name(domain_name): # {'url': domain_name}) # Manually changing the domain name in the conf files. conf_file = '/etc/diaspora.conf' - aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD + - augeas.Augeas.NO_MODL_AUTOLOAD) + aug = augeas.Augeas( + flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD) # lens for shell-script config file aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns') @@ -151,12 +151,10 @@ def subcommand_pre_install(_): def subcommand_enable(_): """Enable web configuration and reload.""" action_utils.service_enable('diaspora') - action_utils.webserver_enable('diaspora-plinth') def subcommand_disable(_): """Disable web configuration and reload.""" - action_utils.webserver_disable('diaspora-plinth') action_utils.service_disable('diaspora') diff --git a/actions/ejabberd b/actions/ejabberd index c38dc35f5..e44e2f031 100755 --- a/actions/ejabberd +++ b/actions/ejabberd @@ -26,9 +26,10 @@ import socket import stat import subprocess import sys -import ruamel.yaml from distutils.version import LooseVersion as LV +import ruamel.yaml + from plinth import action_utils from plinth.modules import config from plinth.modules.letsencrypt import LIVE_DIRECTORY as LE_LIVE_DIRECTORY @@ -131,9 +132,6 @@ def subcommand_setup(_): except subprocess.CalledProcessError as err: print('Failed to restart ejabberd with new configuration: %s', err) - with action_utils.WebserverChange() as webserver_change: - webserver_change.enable('jwchat-plinth') - def upgrade_config(): """Fix the config file by removing deprecated settings""" @@ -167,12 +165,10 @@ def upgrade_config(): def subcommand_enable(_): """Enable XMPP service""" action_utils.service_enable('ejabberd') - action_utils.webserver_enable('jwchat-plinth') def subcommand_disable(_): """Disable XMPP service""" - action_utils.webserver_disable('jwchat-plinth') action_utils.service_disable('ejabberd') @@ -388,8 +384,8 @@ def subcommand_letsencrypt(arguments): def _get_version(): """ Get the current ejabberd version """ try: - output = subprocess.check_output( - ['ejabberdctl', 'status']).decode('utf-8') + output = subprocess.check_output(['ejabberdctl', + 'status']).decode('utf-8') except subprocess.CalledProcessError: return None diff --git a/actions/i2p b/actions/i2p index 2ee857510..f53e87c38 100755 --- a/actions/i2p +++ b/actions/i2p @@ -61,13 +61,11 @@ def parse_arguments(): def subcommand_enable(_): """Enable I2P service.""" action_utils.service_enable('i2p') - action_utils.webserver_enable('i2p-freedombox') def subcommand_disable(_): """Disable I2P service.""" action_utils.service_disable('i2p') - action_utils.webserver_disable('i2p-freedombox') def subcommand_set_tunnel_property(arguments): diff --git a/actions/ikiwiki b/actions/ikiwiki index 6d8e8bad6..7fed468da 100755 --- a/actions/ikiwiki +++ b/actions/ikiwiki @@ -15,7 +15,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # - """ Configuration helper for ikiwiki """ @@ -28,7 +27,6 @@ import sys from plinth import action_utils - SETUP_WIKI = '/etc/ikiwiki/plinth-wiki.setup' SETUP_BLOG = '/etc/ikiwiki/plinth-blog.setup' SITE_PATH = '/var/www/ikiwiki' @@ -43,12 +41,6 @@ def parse_arguments(): # Setup ikiwiki site subparsers.add_parser('setup', help='Perform first time setup operations') - # Enable ikiwiki site - subparsers.add_parser('enable', help='Enable ikiwiki site') - - # Disable ikiwiki site - subparsers.add_parser('disable', help='Disable ikiwiki site') - # Get wikis and blogs subparsers.add_parser('get-sites', help='Get wikis and blogs') @@ -75,16 +67,6 @@ def subcommand_setup(_): setup() -def subcommand_enable(_): - """Enable ikiwiki site.""" - action_utils.webserver_enable('ikiwiki-plinth') - - -def subcommand_disable(_): - """Disable ikiwiki site.""" - action_utils.webserver_disable('ikiwiki-plinth') - - def subcommand_get_sites(_): """Get wikis and blogs.""" try: @@ -97,10 +79,10 @@ def subcommand_get_sites(_): def subcommand_create_wiki(arguments): """Create a wiki.""" pw_bytes = sys.stdin.read().encode() - proc = subprocess.Popen( - ['ikiwiki', '-setup', SETUP_WIKI, - arguments.wiki_name, arguments.admin_name], - stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + proc = subprocess.Popen([ + 'ikiwiki', '-setup', SETUP_WIKI, arguments.wiki_name, + arguments.admin_name + ], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) outs, errs = proc.communicate(input=pw_bytes + b'\n' + pw_bytes) print(outs) print(errs) @@ -109,10 +91,10 @@ def subcommand_create_wiki(arguments): def subcommand_create_blog(arguments): """Create a blog.""" pw_bytes = sys.stdin.read().encode() - proc = subprocess.Popen( - ['ikiwiki', '-setup', SETUP_BLOG, - arguments.blog_name, arguments.admin_name], - stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + proc = subprocess.Popen([ + 'ikiwiki', '-setup', SETUP_BLOG, arguments.blog_name, + arguments.admin_name + ], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) outs, errs = proc.communicate(input=pw_bytes + b'\n' + pw_bytes) print(outs) print(errs) @@ -139,9 +121,6 @@ def setup(): if not os.path.exists(SITE_PATH): os.makedirs(SITE_PATH) - with action_utils.WebserverChange() as webserver_change: - webserver_change.enable('ikiwiki-plinth') - def main(): """Parse arguments and perform all duties.""" diff --git a/actions/matrixsynapse b/actions/matrixsynapse index 48e60df8a..3c153cefd 100755 --- a/actions/matrixsynapse +++ b/actions/matrixsynapse @@ -172,12 +172,10 @@ def subcommand_setup(arguments): def subcommand_enable(_): """Enable service.""" action_utils.service_enable('matrix-synapse') - action_utils.webserver_enable('matrix-synapse-plinth') def subcommand_disable(_): """Disable service.""" - action_utils.webserver_disable('matrix-synapse-plinth') action_utils.service_disable('matrix-synapse') diff --git a/actions/mediawiki b/actions/mediawiki index 8660630f3..f4d76f40d 100755 --- a/actions/mediawiki +++ b/actions/mediawiki @@ -119,14 +119,10 @@ def subcommand_update(_): def subcommand_enable(_): """Enable web configuration and reload.""" action_utils.service_enable('mediawiki-jobrunner') - action_utils.webserver_enable('mediawiki') - action_utils.webserver_enable('mediawiki-freedombox') def subcommand_disable(_): """Disable web configuration and reload.""" - action_utils.webserver_disable('mediawiki') - action_utils.webserver_disable('mediawiki-freedombox') action_utils.service_disable('mediawiki-jobrunner') diff --git a/actions/mldonkey b/actions/mldonkey index 2d3284905..502e8ffb4 100755 --- a/actions/mldonkey +++ b/actions/mldonkey @@ -49,12 +49,10 @@ def subcommand_pre_install(_): def subcommand_enable(_): """Enable web configuration and reload.""" action_utils.service_enable('mldonkey-server') - action_utils.webserver_enable('mldonkey-freedombox') def subcommand_disable(_): """Disable web configuration and reload.""" - action_utils.webserver_disable('mldonkey-freedombox') action_utils.service_disable('mldonkey-server') diff --git a/actions/radicale b/actions/radicale index d1a2ab335..917aa819c 100755 --- a/actions/radicale +++ b/actions/radicale @@ -133,12 +133,9 @@ def subcommand_enable(_): action_utils.service_enable('radicale') action_utils.service_restart('radicale') - action_utils.webserver_enable(radicale.get_web_config()) - def subcommand_disable(_): """Stop service.""" - action_utils.webserver_disable(radicale.get_web_config()) if radicale.get_package_version() >= radicale.VERSION_2: action_utils.uwsgi_disable('radicale') else: diff --git a/actions/repro b/actions/repro index 9fe3b4c4f..20b957696 100755 --- a/actions/repro +++ b/actions/repro @@ -15,7 +15,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # - """ Configuration helper for repro SIP proxy. """ @@ -57,7 +56,6 @@ def subcommand_setup(_): conf.write(line) action_utils.service_restart('repro') - action_utils.webserver_enable('repro-plinth') # We have introduced new firewalld service files and wish to use # them. diff --git a/actions/roundcube b/actions/roundcube index e36136887..bb14d41ad 100755 --- a/actions/roundcube +++ b/actions/roundcube @@ -15,7 +15,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # - """ Configuration helper for Roundcube server. """ @@ -26,7 +25,6 @@ import subprocess from plinth import action_utils - APACHE_CONF = '/etc/apache2/conf-available/roundcube.conf' @@ -39,8 +37,6 @@ def parse_arguments(): help='Perform Roundcube pre-install configuration') subparsers.add_parser('setup', help='Perform Roundcube configuration setup') - subparsers.add_parser('enable', help='Enable Roundcube') - subparsers.add_parser('disable', help='Disable Roundcube') subparsers.required = True return parser.parse_args() @@ -72,16 +68,6 @@ def subcommand_setup(_): action_utils.service_reload('apache2') -def subcommand_enable(_): - """Enable web configuration and reload.""" - action_utils.webserver_enable('roundcube') - - -def subcommand_disable(_): - """Disable web configuration and reload.""" - action_utils.webserver_disable('roundcube') - - def main(): """Parse arguments and perform all duties.""" arguments = parse_arguments() diff --git a/actions/searx b/actions/searx index 2d9ccda4e..6cd4f5bac 100755 --- a/actions/searx +++ b/actions/searx @@ -28,7 +28,6 @@ import augeas import yaml from plinth import action_utils -from plinth.modules.searx import is_public_access_enabled from plinth.modules.searx.manifest import PUBLIC_ACCESS_SETTING_FILE from plinth.utils import gunzip @@ -161,29 +160,22 @@ def subcommand_setup(_): def subcommand_enable(_): """Enable web configuration and reload.""" action_utils.uwsgi_enable('searx') - action_utils.webserver_enable('searx-freedombox') - if not is_public_access_enabled(): - action_utils.webserver_enable('searx-freedombox-auth') def subcommand_disable(_): """Disable web configuration and reload.""" - action_utils.webserver_disable('searx-freedombox') - action_utils.webserver_disable('searx-freedombox-auth') action_utils.uwsgi_disable('searx') def subcommand_enable_public_access(_): """Enable public access to the SearX application.""" open(PUBLIC_ACCESS_SETTING_FILE, 'w').close() - action_utils.webserver_disable('searx-freedombox-auth') def subcommand_disable_public_access(_): """Disable public access to the SearX application.""" if os.path.exists(PUBLIC_ACCESS_SETTING_FILE): os.remove(PUBLIC_ACCESS_SETTING_FILE) - action_utils.webserver_enable('searx-freedombox-auth') def main(): diff --git a/actions/shaarli b/actions/shaarli deleted file mode 100755 index b3c318bf6..000000000 --- a/actions/shaarli +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/python3 -# -# This file is part of FreedomBox. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# - -""" -Configuration helper for Shaarli. -""" - -import argparse - -from plinth import action_utils - - -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('enable', help='Enable Shaarli site') - subparsers.add_parser('disable', help='Disable Shaarli site') - - subparsers.required = True - return parser.parse_args() - - -def subcommand_enable(_): - """Enable web configuration and reload.""" - action_utils.webserver_enable('shaarli') - - -def subcommand_disable(_): - """Disable web configuration and reload.""" - action_utils.webserver_disable('shaarli') - - -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() diff --git a/actions/syncthing b/actions/syncthing index 2cd6fd0fc..f113e6e8a 100755 --- a/actions/syncthing +++ b/actions/syncthing @@ -55,10 +55,11 @@ def setup(): try: pwd.getpwnam('syncthing') except KeyError: - subprocess.run(['adduser', '--system', '--ingroup', 'syncthing', - '--home', '/var/lib/syncthing', - '--gecos', 'Syncthing file synchronization server', - 'syncthing'], check=True) + subprocess.run([ + 'adduser', '--system', '--ingroup', 'syncthing', '--home', + '/var/lib/syncthing', '--gecos', + 'Syncthing file synchronization server', 'syncthing' + ], check=True) if not os.path.exists(data_dir): os.makedirs(data_dir, mode=0o750) @@ -69,12 +70,10 @@ def subcommand_enable(_): """Enable web configuration and reload.""" setup() action_utils.service_enable('syncthing@syncthing') - action_utils.webserver_enable('syncthing-plinth') def subcommand_disable(_): """Disable web configuration and reload.""" - action_utils.webserver_disable('syncthing-plinth') action_utils.service_disable('syncthing@syncthing') diff --git a/actions/tahoe-lafs b/actions/tahoe-lafs index e7ca5f160..829072eeb 100755 --- a/actions/tahoe-lafs +++ b/actions/tahoe-lafs @@ -117,8 +117,8 @@ def subcommand_setup(arguments): def subcommand_autostart(_): """Automatically start all introducers and storage nodes on system startup. """ - aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD + - augeas.Augeas.NO_MODL_AUTOLOAD) + aug = augeas.Augeas( + flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD) aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns') aug.set('/augeas/load/Shellvars/incl[last() + 1]', DEFAULT_FILE) aug.load() @@ -227,12 +227,10 @@ def subcommand_get_local_introducer(_): def subcommand_enable(_): """Enable web configuration and reload.""" action_utils.service_enable('tahoe-lafs') - action_utils.webserver_enable('tahoe-plinth') def subcommand_disable(_): """Disable web configuration and reload.""" - action_utils.webserver_disable('tahoe-plinth') action_utils.service_disable('tahoe-lafs') diff --git a/actions/transmission b/actions/transmission index d74ec0ba0..6445aa036 100755 --- a/actions/transmission +++ b/actions/transmission @@ -50,12 +50,10 @@ def parse_arguments(): def subcommand_enable(_): """Start Transmission service.""" action_utils.service_enable('transmission-daemon') - action_utils.webserver_enable('transmission-plinth') def subcommand_disable(_): """Stop Transmission service.""" - action_utils.webserver_disable('transmission-plinth') action_utils.service_disable('transmission-daemon') diff --git a/actions/ttrss b/actions/ttrss index 5cf2f45b0..d519f565a 100755 --- a/actions/ttrss +++ b/actions/ttrss @@ -15,16 +15,16 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # - """ Configuration helper for Tiny Tiny RSS. """ import argparse -import augeas import os import subprocess +import augeas + from plinth import action_utils CONFIG_FILE = '/etc/tt-rss/config.php' @@ -52,9 +52,8 @@ def parse_arguments(): def subcommand_pre_setup(_): """Preseed debconf values before packages are installed.""" - subprocess.check_output( - ['debconf-set-selections'], - input=b'tt-rss tt-rss/database-type string pgsql') + subprocess.check_output(['debconf-set-selections'], + input=b'tt-rss tt-rss/database-type string pgsql') def subcommand_setup(_): @@ -101,8 +100,8 @@ def enable_api_access(): database = get_value('dbname') host = get_value('dbserver') - connection = psycopg2.connect( - database=database, user=user, password=password, host=host) + connection = psycopg2.connect(database=database, user=user, + password=password, host=host) cursor = connection.cursor() cursor.execute("UPDATE ttrss_prefs SET def_value=true " @@ -115,13 +114,11 @@ def enable_api_access(): def subcommand_enable(_): """Enable web configuration and reload.""" action_utils.service_enable('tt-rss') - action_utils.webserver_enable('tt-rss-plinth') enable_api_access() def subcommand_disable(_): """Disable web configuration and reload.""" - action_utils.webserver_disable('tt-rss-plinth') action_utils.service_disable('tt-rss') @@ -148,8 +145,8 @@ def _run_as_postgres(command, stdin=None, stdout=None): def load_augeas(): """Initialize Augeas.""" - aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD + - augeas.Augeas.NO_MODL_AUTOLOAD) + aug = augeas.Augeas( + flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD) aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns') aug.set('/augeas/load/Shellvars/incl[last() + 1]', DEFAULT_FILE) aug.set('/augeas/load/Phpvars/lens', 'Phpvars.lns') diff --git a/plinth/app.py b/plinth/app.py index bf69605db..a67126002 100644 --- a/plinth/app.py +++ b/plinth/app.py @@ -57,7 +57,7 @@ class App: def disable(self): """Enable all the components of the app.""" - for component in self.components.values(): + for component in reversed(self.components.values()): component.disable() def is_enabled(self): diff --git a/plinth/modules/apache/components.py b/plinth/modules/apache/components.py new file mode 100644 index 000000000..dbc6c623a --- /dev/null +++ b/plinth/modules/apache/components.py @@ -0,0 +1,60 @@ +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +""" +App component for other apps to use Apache configuration functionality. +""" + +from plinth import action_utils, actions, app + + +class Webserver(app.LeaderComponent): + """Component to enable/disable Apache configuration.""" + + def __init__(self, component_id, web_name, kind='config'): + """Initialize the web server component. + + component_id should be a unique ID across all components of an app and + across all components. + + web_name is the primary part of the configuration file path which must + be enabled/disabled by this component. + + kind is the type of Apache configuration being enabled/disabled. This + must be 'config' for a configuration in /etc/apache/conf-available/, + 'module' for configuration in /etc/apache2/mods-available/, 'site' for + configuration in /etc/apache2/sites-available/. + + """ + super().__init__(component_id) + + self.web_name = web_name + self.kind = kind + + def is_enabled(self): + """Return whether the Apache configuration is enabled.""" + return action_utils.webserver_is_enabled(self.web_name, kind=self.kind) + + def enable(self): + """Enable the Apache configuration.""" + actions.superuser_run( + 'apache', ['enable', '--name', self.web_name, '--kind', self.kind]) + + def disable(self): + """Disable the Apache configuration.""" + actions.superuser_run( + 'apache', + ['disable', '--name', self.web_name, '--kind', self.kind]) diff --git a/plinth/modules/apache/tests/test_components.py b/plinth/modules/apache/tests/test_components.py new file mode 100644 index 000000000..bc75af8bc --- /dev/null +++ b/plinth/modules/apache/tests/test_components.py @@ -0,0 +1,77 @@ +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +""" +Test module for webserver components. +""" + +from unittest.mock import call, patch + +import pytest + +from plinth.modules.apache.components import Webserver + + +def test_webserver_init(): + """Test that webserver component can be initialized.""" + with pytest.raises(ValueError): + Webserver(None, None) + + webserver = Webserver('test-webserver', 'test-config', kind='module') + assert webserver.component_id == 'test-webserver' + assert webserver.web_name == 'test-config' + assert webserver.kind == 'module' + + webserver = Webserver('test-webserver', None) + assert webserver.kind == 'config' + + +@patch('plinth.action_utils.webserver_is_enabled') +def test_webserver_is_enabled(webserver_is_enabled): + """Test that checking webserver configuration enabled works.""" + webserver = Webserver('test-webserver', 'test-config', kind='module') + + webserver_is_enabled.return_value = True + assert webserver.is_enabled() + webserver_is_enabled.assert_has_calls([call('test-config', kind='module')]) + + webserver_is_enabled.reset_mock() + webserver_is_enabled.return_value = False + assert not webserver.is_enabled() + webserver_is_enabled.assert_has_calls([call('test-config', kind='module')]) + + +@patch('plinth.actions.superuser_run') +def test_webserver_enable(superuser_run): + """Test that enabling webserver configuration works.""" + webserver = Webserver('test-webserver', 'test-config', kind='module') + + webserver.enable() + superuser_run.assert_has_calls([ + call('apache', ['enable', '--name', 'test-config', '--kind', 'module']) + ]) + + +@patch('plinth.actions.superuser_run') +def test_webserver_disable(superuser_run): + """Test that disabling webserver configuration works.""" + webserver = Webserver('test-webserver', 'test-config', kind='module') + + webserver.disable() + superuser_run.assert_has_calls([ + call('apache', + ['disable', '--name', 'test-config', '--kind', 'module']) + ]) diff --git a/plinth/modules/cockpit/__init__.py b/plinth/modules/cockpit/__init__.py index cdbe925d1..217aaef1c 100644 --- a/plinth/modules/cockpit/__init__.py +++ b/plinth/modules/cockpit/__init__.py @@ -26,6 +26,7 @@ from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth import service as service_module from plinth.modules import names +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.signals import domain_added, domain_removed, domainname_change from plinth.utils import format_lazy @@ -85,6 +86,9 @@ class CockpitApp(app_module.App): is_external=True) self.add(firewall) + webserver = Webserver('webserver-cockpit', 'cockpit-freedombox') + self.add(webserver) + def init(): """Intialize the module.""" @@ -124,7 +128,7 @@ def setup(helper, old_version=None): def is_enabled(): """Return whether the module is enabled.""" - return (action_utils.webserver_is_enabled('cockpit-freedombox') + return (app.is_enabled() and action_utils.service_is_running('cockpit.socket')) diff --git a/plinth/modules/coquelicot/__init__.py b/plinth/modules/coquelicot/__init__.py index fa28b3bf2..9f492500d 100644 --- a/plinth/modules/coquelicot/__init__.py +++ b/plinth/modules/coquelicot/__init__.py @@ -24,6 +24,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from .manifest import backup, clients @@ -78,6 +79,8 @@ class CoquelicotApp(app_module.App): ports=['http', 'https'], is_external=True) self.add(firewall) + webserver = Webserver('webserver-coquelicot', 'coquelicot-freedombox') + self.add(webserver) def init(): @@ -116,8 +119,7 @@ def is_running(): def is_enabled(): """Return whether the module is enabled.""" - return (action_utils.service_is_enabled('coquelicot') - and action_utils.webserver_is_enabled('coquelicot-freedombox')) + return (action_utils.service_is_enabled('coquelicot') and app.is_enabled()) def enable(): diff --git a/plinth/modules/deluge/__init__.py b/plinth/modules/deluge/__init__.py index 915a9ccd5..efd07d0fd 100644 --- a/plinth/modules/deluge/__init__.py +++ b/plinth/modules/deluge/__init__.py @@ -24,6 +24,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.modules.users import register_group @@ -80,6 +81,9 @@ class DelugeApp(app_module.App): is_external=True) self.add(firewall) + webserver = Webserver('webserver-deluge', 'deluge-plinth') + self.add(webserver) + def init(): """Initialize the Deluge module.""" @@ -111,8 +115,7 @@ def setup(helper, old_version=None): def is_enabled(): """Return whether the module is enabled.""" - return (action_utils.webserver_is_enabled('deluge-plinth') - and action_utils.service_is_enabled('deluge-web')) + return (app.is_enabled() and action_utils.service_is_enabled('deluge-web')) def enable(): diff --git a/plinth/modules/diaspora/__init__.py b/plinth/modules/diaspora/__init__.py index d737cfade..a983158be 100644 --- a/plinth/modules/diaspora/__init__.py +++ b/plinth/modules/diaspora/__init__.py @@ -24,6 +24,7 @@ from plinth import app as app_module from plinth import frontpage, menu from plinth import service as service_module from plinth.errors import DomainNotRegisteredError +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.utils import format_lazy @@ -97,6 +98,9 @@ class DiasporaApp(app_module.App): is_external=True) self.add(firewall) + webserver = Webserver('webserver-diaspora', 'diaspora-plinth') + self.add(webserver) + class Shortcut(frontpage.Shortcut): """Frontpage shortcut to use configured domain name for URL.""" @@ -143,7 +147,7 @@ def setup_domain_name(domain_name): def is_enabled(): """Return whether the module is enabled.""" - return action_utils.webserver_is_enabled('diaspora-plinth') + return app.is_enabled() def enable(): diff --git a/plinth/modules/ejabberd/__init__.py b/plinth/modules/ejabberd/__init__.py index ba2a36575..8b6f039a1 100644 --- a/plinth/modules/ejabberd/__init__.py +++ b/plinth/modules/ejabberd/__init__.py @@ -28,6 +28,7 @@ from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth import service as service_module from plinth.modules import config +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.signals import (domainname_change, post_hostname_change, pre_hostname_change) @@ -100,6 +101,9 @@ class EjabberdApp(app_module.App): 'xmpp-bosh'], is_external=True) self.add(firewall) + webserver = Webserver('webserver-ejabberd', 'jwchat-plinth') + self.add(webserver) + def init(): """Initialize the ejabberd module""" diff --git a/plinth/modules/i2p/__init__.py b/plinth/modules/i2p/__init__.py index 0da020b22..7260b7f44 100644 --- a/plinth/modules/i2p/__init__.py +++ b/plinth/modules/i2p/__init__.py @@ -24,6 +24,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.modules.i2p.resources import FAVORITES from plinth.modules.users import register_group @@ -101,6 +102,9 @@ class I2PApp(app_module.App): is_external=False) self.add(firewall) + webserver = Webserver('webserver-i2p', 'i2p-freedombox') + self.add(webserver) + def init(): """Intialize the module.""" @@ -163,8 +167,7 @@ def is_running(): def is_enabled(): """Return whether the module is enabled.""" - return action_utils.service_is_enabled('i2p') and \ - action_utils.webserver_is_enabled('i2p-freedombox') + return action_utils.service_is_enabled('i2p') and app.is_enabled() def enable(): diff --git a/plinth/modules/ikiwiki/__init__.py b/plinth/modules/ikiwiki/__init__.py index c33c83bfe..1f8225b93 100644 --- a/plinth/modules/ikiwiki/__init__.py +++ b/plinth/modules/ikiwiki/__init__.py @@ -25,6 +25,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.modules.users import register_group from plinth.utils import format_lazy @@ -88,6 +89,9 @@ class IkiwikiApp(app_module.App): is_external=True) self.add(firewall) + webserver = Webserver('webserver-ikiwiki', 'ikiwiki-plinth') + self.add(webserver) + def add_shortcut(self, site): """Add an ikiwiki shortcut to frontpage.""" shortcut = frontpage.Shortcut('shortcut-ikiwiki-' + site, site, @@ -132,18 +136,16 @@ def setup(helper, old_version=None): def is_enabled(): """Return whether the module is enabled.""" - return action_utils.webserver_is_enabled('ikiwiki-plinth') + return app.is_enabled() def enable(): """Enable the module.""" - actions.superuser_run('ikiwiki', ['enable']) app.enable() def disable(): """Enable the module.""" - actions.superuser_run('ikiwiki', ['disable']) app.disable() diff --git a/plinth/modules/matrixsynapse/__init__.py b/plinth/modules/matrixsynapse/__init__.py index 6e6981fe6..e88fb2f31 100644 --- a/plinth/modules/matrixsynapse/__init__.py +++ b/plinth/modules/matrixsynapse/__init__.py @@ -29,6 +29,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from .manifest import backup, clients @@ -96,6 +97,10 @@ class MatrixSynapseApp(app_module.App): ports=['matrix-synapse-plinth'], is_external=True) self.add(firewall) + webserver = Webserver('webserver-matrixsynapse', + 'matrix-synapse-plinth') + self.add(webserver) + def init(): """Initialize the matrix-synapse module.""" @@ -133,7 +138,8 @@ def is_setup(): def is_enabled(): """Return whether the module is enabled.""" - return action_utils.service_is_enabled('matrix-synapse') + return (action_utils.service_is_enabled('matrix-synapse') + and app.is_enabled()) def enable(): diff --git a/plinth/modules/mediawiki/__init__.py b/plinth/modules/mediawiki/__init__.py index 836181901..16761526d 100644 --- a/plinth/modules/mediawiki/__init__.py +++ b/plinth/modules/mediawiki/__init__.py @@ -24,6 +24,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from .manifest import backup, clients @@ -83,6 +84,13 @@ class MediaWikiApp(app_module.App): ports=['http', 'https'], is_external=True) self.add(firewall) + webserver = Webserver('webserver-mediawiki', 'mediawiki') + self.add(webserver) + + webserver = Webserver('webserver-mediawiki-freedombox', + 'mediawiki-freedombox') + self.add(webserver) + class Shortcut(frontpage.Shortcut): """Frontpage shortcut for only logged users when in private mode.""" @@ -124,7 +132,7 @@ def setup(helper, old_version=None): def is_enabled(): """Return whether the module is enabled.""" - return action_utils.webserver_is_enabled('mediawiki') + return app.is_enabled() def enable(): diff --git a/plinth/modules/mldonkey/__init__.py b/plinth/modules/mldonkey/__init__.py index b5acb80b6..8b8f6a7ef 100644 --- a/plinth/modules/mldonkey/__init__.py +++ b/plinth/modules/mldonkey/__init__.py @@ -24,6 +24,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.modules.users import register_group from plinth.utils import format_lazy @@ -83,10 +84,12 @@ class MLDonkeyApp(app_module.App): clients=clients, allowed_groups=[group[0]]) self.add(shortcuts) - firewall = Firewall('firewall-mldonkey', name, - ports=['http', 'https'], is_external=True) + firewall = Firewall('firewall-mldonkey', name, ports=['http', 'https'], + is_external=True) self.add(firewall) + webserver = Webserver('webserver-mldonkey', 'mldonkey-freedombox') + self.add(webserver) def init(): @@ -127,7 +130,7 @@ def is_running(): def is_enabled(): """Return whether the module is enabled.""" return (action_utils.service_is_enabled('mldonkey-server') - and action_utils.webserver_is_enabled('mldonkey-freedombox')) + and app.is_enabled()) def enable(): diff --git a/plinth/modules/radicale/__init__.py b/plinth/modules/radicale/__init__.py index e26d5bbb3..214d5e73d 100644 --- a/plinth/modules/radicale/__init__.py +++ b/plinth/modules/radicale/__init__.py @@ -30,6 +30,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.utils import format_lazy @@ -91,10 +92,30 @@ class RadicaleApp(app_module.App): clients=clients, login_required=True) self.add(shortcut) - firewall = Firewall('firewall-radicale', name, - ports=['http', 'https'], is_external=True) + firewall = Firewall('firewall-radicale', name, ports=['http', 'https'], + is_external=True) self.add(firewall) + webserver = RadicaleWebserver('webserver-radicale', None) + self.add(webserver) + + +class RadicaleWebserver(Webserver): + """Webserver enable/disable behavior specific for radicale.""" + + @property + def web_name(self): + """Return web configuration name based on radicale version.""" + current_version = get_package_version() + if current_version and current_version < VERSION_2: + return 'radicale-plinth' + + return 'radicale2-freedombox' + + @web_name.setter + def web_name(self, web_name): + """Set the web name""" + def init(): """Initialize the radicale module.""" @@ -158,17 +179,6 @@ def get_package_version(): return LV(package_version) -def get_web_config(current_version=None): - """Return the name of the webserver configuration based on version.""" - if current_version is None: - current_version = get_package_version() - - if current_version and current_version < VERSION_2: - return 'radicale-plinth' - - return 'radicale2-freedombox' - - def is_running(): """Return whether the service is running.""" if get_package_version() < VERSION_2: @@ -186,8 +196,7 @@ def is_enabled(): else: daemon_enabled = action_utils.service_is_enabled('radicale') - return (action_utils.webserver_is_enabled(get_web_config(package_version)) - and daemon_enabled) + return (app.is_enabled() and daemon_enabled) def enable(): diff --git a/plinth/modules/repro/__init__.py b/plinth/modules/repro/__init__.py index 32d669903..5fee5e8fd 100644 --- a/plinth/modules/repro/__init__.py +++ b/plinth/modules/repro/__init__.py @@ -25,6 +25,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.views import ServiceView @@ -94,6 +95,9 @@ class ReproApp(app_module.App): 'rtp-plinth'], is_external=True) self.add(firewall) + webserver = Webserver('webserver-repro', 'repro-plinth') + self.add(webserver) + def init(): """Initialize the repro module.""" diff --git a/plinth/modules/roundcube/__init__.py b/plinth/modules/roundcube/__init__.py index 17c06de51..cae9311ed 100644 --- a/plinth/modules/roundcube/__init__.py +++ b/plinth/modules/roundcube/__init__.py @@ -24,6 +24,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from .manifest import backup, clients @@ -86,6 +87,9 @@ class RoundcubeApp(app_module.App): ports=['http', 'https'], is_external=True) self.add(firewall) + webserver = Webserver('webserver-roundcube', 'roundcube') + self.add(webserver) + def init(): """Intialize the module.""" @@ -118,18 +122,16 @@ def setup(helper, old_version=None): def is_enabled(): """Return whether the module is enabled.""" - return action_utils.webserver_is_enabled('roundcube') + return app.is_enabled() def enable(): """Enable the module.""" - actions.superuser_run('roundcube', ['enable']) app.enable() def disable(): """Enable the module.""" - actions.superuser_run('roundcube', ['disable']) app.disable() diff --git a/plinth/modules/searx/__init__.py b/plinth/modules/searx/__init__.py index bd97f8a9c..ebd67e49c 100644 --- a/plinth/modules/searx/__init__.py +++ b/plinth/modules/searx/__init__.py @@ -26,6 +26,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.modules.users import register_group @@ -80,6 +81,13 @@ class SearxApp(app_module.App): is_external=True) self.add(firewall) + webserver = Webserver('webserver-searx', 'searx-freedombox') + self.add(webserver) + + webserver = SearxWebserverAuth('webserver-searx-auth', + 'searx-freedombox-auth') + self.add(webserver) + def set_shortcut_login_required(self, login_required): """Change the login_required property of shortcut.""" shortcut = self.remove('shortcut-searx') @@ -87,6 +95,19 @@ class SearxApp(app_module.App): self.add(shortcut) +class SearxWebserverAuth(Webserver): + """Component to handle Searx authentication webserver configuration.""" + + def is_enabled(self): + """Return if configuration is enabled or public access is enabled.""" + return is_public_access_enabled() or super().is_enabled() + + def enable(self): + """Enable apache configuration only if public access is disabled.""" + if not is_public_access_enabled(): + super().enable() + + def init(): """Intialize the module.""" global app @@ -136,8 +157,7 @@ def is_public_access_enabled(): def is_enabled(): """Return whether the module is enabled.""" - return (action_utils.webserver_is_enabled('searx-freedombox') - and action_utils.uwsgi_is_enabled('searx')) + return (app.is_enabled() and action_utils.uwsgi_is_enabled('searx')) def enable(): @@ -166,10 +186,12 @@ def diagnose(): def enable_public_access(): """Allow Searx app to be accessed by anyone with access.""" actions.superuser_run('searx', ['enable-public-access']) + app.get_component('webserver-searx-auth').disable() app.set_shortcut_login_required(False) def disable_public_access(): """Allow Searx app to be accessed by logged-in users only.""" actions.superuser_run('searx', ['disable-public-access']) + app.get_component('webserver-searx-auth').enable() app.set_shortcut_login_required(True) diff --git a/plinth/modules/shaarli/__init__.py b/plinth/modules/shaarli/__init__.py index 7e0068c31..bc1f1b246 100644 --- a/plinth/modules/shaarli/__init__.py +++ b/plinth/modules/shaarli/__init__.py @@ -20,10 +20,10 @@ FreedomBox app to configure Shaarli. from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions from plinth import app as app_module from plinth import frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from .manifest import clients @@ -74,6 +74,9 @@ class ShaarliApp(app_module.App): is_external=True) self.add(firewall) + webserver = Webserver('webserver-shaarli', 'shaarli') + self.add(webserver) + def init(): """Initialize the module.""" @@ -104,16 +107,14 @@ def setup(helper, old_version=None): def is_enabled(): """Return whether the module is enabled.""" - return action_utils.webserver_is_enabled('shaarli') + return app.is_enabled() def enable(): """Enable the module.""" - actions.superuser_run('shaarli', ['enable']) app.enable() def disable(): """Enable the module.""" - actions.superuser_run('shaarli', ['disable']) app.disable() diff --git a/plinth/modules/syncthing/__init__.py b/plinth/modules/syncthing/__init__.py index 6df1add5a..0bdc9fb82 100644 --- a/plinth/modules/syncthing/__init__.py +++ b/plinth/modules/syncthing/__init__.py @@ -24,6 +24,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.modules.users import register_group from plinth.utils import format_lazy @@ -90,6 +91,9 @@ class SyncthingApp(app_module.App): ports=['http', 'https'], is_external=True) self.add(firewall) + webserver = Webserver('webserver-syncthing', 'syncthing-plinth') + self.add(webserver) + def init(): """Intialize the module.""" @@ -128,7 +132,7 @@ def is_running(): def is_enabled(): """Return whether the module is enabled.""" return (action_utils.service_is_enabled('syncthing@syncthing') - and action_utils.webserver_is_enabled('syncthing-plinth')) + and app.is_enabled()) def enable(): diff --git a/plinth/modules/tahoe/__init__.py b/plinth/modules/tahoe/__init__.py index b3c8cbce9..0b7de60d8 100644 --- a/plinth/modules/tahoe/__init__.py +++ b/plinth/modules/tahoe/__init__.py @@ -27,6 +27,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.utils import format_lazy @@ -82,6 +83,9 @@ class TahoeApp(app_module.App): is_external=True) self.add(firewall) + webserver = Webserver('webserver-tahoe', 'tahoe-plinth') + self.add(webserver) + class Shortcut(frontpage.Shortcut): """Frontpage shortcut to use configured domain name for URL.""" @@ -168,7 +172,7 @@ def is_running(): def is_enabled(): """Return whether the module is enabled.""" return (action_utils.service_is_enabled(managed_services[0]) - and action_utils.webserver_is_enabled('tahoe-plinth')) + and app.is_enabled()) def enable(): diff --git a/plinth/modules/transmission/__init__.py b/plinth/modules/transmission/__init__.py index 4638ab5db..95465eb03 100644 --- a/plinth/modules/transmission/__init__.py +++ b/plinth/modules/transmission/__init__.py @@ -26,6 +26,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.modules.users import register_group @@ -82,6 +83,9 @@ class TransmissionApp(app_module.App): ports=['http', 'https'], is_external=True) self.add(firewall) + webserver = Webserver('webserver-transmission', 'transmission-plinth') + self.add(webserver) + def init(): """Initialize the Transmission module.""" @@ -124,7 +128,7 @@ def setup(helper, old_version=None): def is_enabled(): """Return whether the module is enabled.""" return (action_utils.service_is_enabled('transmission-daemon') - and action_utils.webserver_is_enabled('transmission-plinth')) + and app.is_enabled()) def enable(): diff --git a/plinth/modules/ttrss/__init__.py b/plinth/modules/ttrss/__init__.py index 558541119..8d123bb3d 100644 --- a/plinth/modules/ttrss/__init__.py +++ b/plinth/modules/ttrss/__init__.py @@ -25,6 +25,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth import service as service_module +from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.modules.users import register_group from plinth.utils import Version, format_lazy @@ -88,6 +89,9 @@ class TTRSSApp(app_module.App): is_external=True) self.add(firewall) + webserver = Webserver('webserver-ttrss', 'tt-rss-plinth') + self.add(webserver) + def init(): """Intialize the module.""" @@ -137,8 +141,7 @@ def force_upgrade(helper, packages): def is_enabled(): """Return whether the module is enabled.""" - return (action_utils.service_is_enabled('tt-rss') - and action_utils.webserver_is_enabled('tt-rss-plinth')) + return (action_utils.service_is_enabled('tt-rss') and app.is_enabled()) def enable():