From ca2c7dbeb0ecf5aa7eb45329db037b960864fe0b Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Tue, 21 May 2019 09:08:35 -0700 Subject: [PATCH] Introduce firewall component for opening/closing ports Signed-off-by: Sunil Mohan Adapa Reviewed-by: James Valleroy --- plinth/__main__.py | 2 - plinth/app.py | 17 ++- plinth/modules/apache/__init__.py | 39 ++++- plinth/modules/avahi/__init__.py | 8 +- plinth/modules/bind/__init__.py | 10 +- plinth/modules/cockpit/__init__.py | 16 +- plinth/modules/coquelicot/__init__.py | 23 +-- plinth/modules/datetime/__init__.py | 7 +- plinth/modules/deluge/__init__.py | 16 +- plinth/modules/diaspora/__init__.py | 16 +- plinth/modules/ejabberd/__init__.py | 23 +-- plinth/modules/firewall/__init__.py | 53 ------- plinth/modules/firewall/components.py | 106 +++++++++++++ .../modules/firewall/templates/firewall.html | 20 +-- .../modules/firewall/tests/test_components.py | 139 ++++++++++++++++++ plinth/modules/firewall/views.py | 12 +- plinth/modules/i2p/__init__.py | 40 +++-- plinth/modules/ikiwiki/__init__.py | 18 ++- plinth/modules/infinoted/__init__.py | 16 +- plinth/modules/jsxc/__init__.py | 15 +- plinth/modules/matrixsynapse/__init__.py | 16 +- plinth/modules/mediawiki/__init__.py | 24 ++- plinth/modules/minetest/__init__.py | 16 +- plinth/modules/mldonkey/__init__.py | 23 +-- plinth/modules/mumble/__init__.py | 16 +- plinth/modules/openvpn/__init__.py | 9 +- plinth/modules/openvpn/views.py | 2 - plinth/modules/privoxy/__init__.py | 8 +- plinth/modules/quassel/__init__.py | 16 +- plinth/modules/radicale/__init__.py | 22 +-- plinth/modules/repro/__init__.py | 17 ++- plinth/modules/restore/__init__.py | 13 +- plinth/modules/roundcube/__init__.py | 17 ++- plinth/modules/searx/__init__.py | 15 +- plinth/modules/shaarli/__init__.py | 18 ++- plinth/modules/shadowsocks/__init__.py | 20 ++- plinth/modules/ssh/__init__.py | 10 +- plinth/modules/storage/__init__.py | 6 +- plinth/modules/syncthing/__init__.py | 22 +-- plinth/modules/tahoe/__init__.py | 22 +-- plinth/modules/tor/__init__.py | 43 +++--- plinth/modules/tor/views.py | 2 - plinth/modules/transmission/__init__.py | 16 +- plinth/modules/ttrss/__init__.py | 16 +- plinth/modules/upgrades/__init__.py | 2 +- plinth/service.py | 51 +------ plinth/signals.py | 1 - plinth/tests/test_app.py | 9 ++ 48 files changed, 647 insertions(+), 401 deletions(-) create mode 100644 plinth/modules/firewall/components.py create mode 100644 plinth/modules/firewall/tests/test_components.py diff --git a/plinth/__main__.py b/plinth/__main__.py index bd1ae297f..bd65554ff 100644 --- a/plinth/__main__.py +++ b/plinth/__main__.py @@ -147,8 +147,6 @@ def main(): log.init() - service.init() - web_framework.init() logger.info('FreedomBox Service (Plinth) version - %s', __version__) diff --git a/plinth/app.py b/plinth/app.py index cb9292d45..bf69605db 100644 --- a/plinth/app.py +++ b/plinth/app.py @@ -74,10 +74,7 @@ class App: """ for component in self.components.values(): if not component.is_leader: - if enabled: - component.enable() - else: - component.disable() + component.set_enabled(enabled) class Component: @@ -93,10 +90,10 @@ class Component: self.component_id = component_id def enable(self): - """Enable the component.""" + """Run operations to enable the component.""" def disable(self): - """Disable the component.""" + """Run operations to disable the component.""" class FollowerComponent(Component): @@ -117,12 +114,16 @@ class FollowerComponent(Component): """Return whether the component is enabled.""" return self._is_enabled + def set_enabled(self, enabled): + """Update the internal enabled state of the component.""" + self._is_enabled = enabled + def enable(self): - """Enable the component.""" + """Run operations to enable the component.""" self._is_enabled = True def disable(self): - """Disable the component.""" + """Run operations to disable the component.""" self._is_enabled = False diff --git a/plinth/modules/apache/__init__.py b/plinth/modules/apache/__init__.py index 9d2a96fae..536b6a4b1 100644 --- a/plinth/modules/apache/__init__.py +++ b/plinth/modules/apache/__init__.py @@ -18,7 +18,13 @@ FreedomBox app for Apache server. """ +from django.utils.translation import ugettext_lazy as _ + from plinth import actions +from plinth import app as app_module +from plinth import cfg +from plinth.modules.firewall.components import Firewall +from plinth.utils import format_lazy version = 7 @@ -26,9 +32,38 @@ is_essential = True managed_packages = ['apache2', 'php-fpm'] +app = None + + +class ApacheApp(app_module.App): + """FreedomBox app for Apache web server.""" + + def __init__(self): + """Create components for the app.""" + super().__init__() + + web_server_ports = Firewall('firewall-web', _('Web Server'), + ports=['http', 'https'], is_external=True) + self.add(web_server_ports) + + freedombox_ports = Firewall( + 'firewall-plinth', + format_lazy( + _('{box_name} Web Interface (Plinth)'), box_name=_( + cfg.box_name)), ports=['http', 'https'], is_external=True) + self.add(freedombox_ports) + + +def init(): + """Initailze firewall module""" + global app + app = ApacheApp() + app.set_enabled(True) + def setup(helper, old_version=None): """Configure the module.""" helper.install(managed_packages) - actions.superuser_run('apache', - ['setup', '--old-version', str(old_version)]) + actions.superuser_run( + 'apache', + ['setup', '--old-version', str(old_version)]) diff --git a/plinth/modules/avahi/__init__.py b/plinth/modules/avahi/__init__.py index 2dd1bc15d..31e824907 100644 --- a/plinth/modules/avahi/__init__.py +++ b/plinth/modules/avahi/__init__.py @@ -24,6 +24,7 @@ from plinth import actions from plinth import app as app_module from plinth import cfg, menu from plinth import service as service_module +from plinth.modules.firewall.components import Firewall from plinth.utils import format_lazy from plinth.views import ServiceView @@ -69,6 +70,10 @@ class AvahiApp(app_module.App): 'avahi:index', parent_url_name='system') self.add(menu_item) + firewall = Firewall('firewall-avahi', name, ports=['mdns'], + is_external=False) + self.add(firewall) + def init(): """Intialize the service discovery module.""" @@ -77,8 +82,7 @@ def init(): app.set_enabled(True) global service # pylint: disable=W0603 - service = service_module.Service(managed_services[0], name, ports=['mdns'], - is_external=False) + service = service_module.Service(managed_services[0], name) def setup(helper, old_version=None): diff --git a/plinth/modules/bind/__init__.py b/plinth/modules/bind/__init__.py index 32f6f1c05..34a341862 100644 --- a/plinth/modules/bind/__init__.py +++ b/plinth/modules/bind/__init__.py @@ -26,6 +26,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import cfg, menu from plinth import service as service_module +from plinth.modules.firewall.components import Firewall from plinth.utils import format_lazy from .manifest import backup @@ -97,6 +98,10 @@ class BindApp(app_module.App): parent_url_name='system') self.add(menu_item) + firewall = Firewall('firewall-bind', name, ports=['dns'], + is_external=False) + self.add(firewall) + def init(): """Intialize the BIND module.""" @@ -106,8 +111,7 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, - ports=['dns'], is_external=False) + service = service_module.Service(managed_services[0], name) app.set_enabled(True) # XXX: Perform better check @@ -117,9 +121,7 @@ def setup(helper, old_version=None): global service if service is None: service = service_module.Service(managed_services[0], name, - ports=['dns'], is_external=True, enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) helper.call('post', actions.superuser_run, 'bind', ['setup']) helper.call('post', app.enable) diff --git a/plinth/modules/cockpit/__init__.py b/plinth/modules/cockpit/__init__.py index 3dc50ef80..cdbe925d1 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.firewall.components import Firewall from plinth.signals import domain_added, domain_removed, domainname_change from plinth.utils import format_lazy @@ -80,6 +81,10 @@ class CockpitApp(app_module.App): clients=clients, login_required=True) self.add(shortcut) + firewall = Firewall('firewall-cockpit', name, ports=['http', 'https'], + is_external=True) + self.add(firewall) + def init(): """Intialize the module.""" @@ -89,9 +94,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service(managed_services[0], name, + is_enabled=is_enabled, enable=enable, disable=disable) if is_enabled(): @@ -112,11 +116,9 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'cockpit', ['setup'] + domains) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service(managed_services[0], name, + is_enabled=is_enabled, enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) helper.call('post', app.enable) diff --git a/plinth/modules/coquelicot/__init__.py b/plinth/modules/coquelicot/__init__.py index d8e13ba6e..fa28b3bf2 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.firewall.components import Firewall from .manifest import backup, clients @@ -73,6 +74,11 @@ class CoquelicotApp(app_module.App): clients=clients, login_required=True) self.add(shortcut) + firewall = Firewall('firewall-coquelicot', name, + ports=['http', 'https'], is_external=True) + self.add(firewall) + + def init(): """Intialize the module.""" @@ -82,11 +88,9 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, - disable=disable, - is_running=is_running) + service = service_module.Service( + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) if is_enabled(): app.set_enabled(True) @@ -99,12 +103,9 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'coquelicot', ['enable']) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, - disable=disable, - is_running=is_running) - helper.call('post', service.notify_enabled, None, True) + service = service_module.Service( + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) helper.call('post', app.enable) diff --git a/plinth/modules/datetime/__init__.py b/plinth/modules/datetime/__init__.py index d6b014f5b..2b7b40681 100644 --- a/plinth/modules/datetime/__init__.py +++ b/plinth/modules/datetime/__init__.py @@ -70,18 +70,15 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, - is_external=True) + service = service_module.Service(managed_services[0], name) def setup(helper, old_version=None): """Install and configure the module.""" global service if service is None: - service = service_module.Service(managed_services[0], name, - is_external=True) + service = service_module.Service(managed_services[0], name) service.enable() - helper.call('post', service.notify_enabled, None, True) helper.call('post', app.enable) diff --git a/plinth/modules/deluge/__init__.py b/plinth/modules/deluge/__init__.py index 7df379187..915a9ccd5 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.firewall.components import Firewall from plinth.modules.users import register_group from .manifest import backup, clients @@ -75,6 +76,10 @@ class DelugeApp(app_module.App): allowed_groups=[group[0]]) self.add(shortcut) + firewall = Firewall('firewall-deluge', name, ports=['http', 'https'], + is_external=True) + self.add(firewall) + def init(): """Initialize the Deluge module.""" @@ -85,9 +90,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service(managed_services[0], name, + is_enabled=is_enabled, enable=enable, disable=disable) if is_enabled(): app.set_enabled(True) @@ -99,11 +103,9 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'deluge', ['enable']) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service(managed_services[0], name, + is_enabled=is_enabled, enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) helper.call('post', app.enable) diff --git a/plinth/modules/diaspora/__init__.py b/plinth/modules/diaspora/__init__.py index ab32ac417..d737cfade 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.firewall.components import Firewall from plinth.utils import format_lazy domain_name_file = "/etc/diaspora/domain_name" @@ -92,6 +93,10 @@ class DiasporaApp(app_module.App): icon='diaspora', url=None, clients=clients, login_required=True) self.add(shortcut) + firewall = Firewall('firewall-diaspora', name, ports=['http', 'https'], + is_external=True) + self.add(firewall) + class Shortcut(frontpage.Shortcut): """Frontpage shortcut to use configured domain name for URL.""" @@ -110,9 +115,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service(managed_services[0], name, + is_enabled=is_enabled, enable=enable, disable=disable) if is_enabled(): @@ -131,11 +135,9 @@ def setup_domain_name(domain_name): actions.superuser_run('diaspora', ['setup', '--domain-name', domain_name]) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service(managed_services[0], name, + is_enabled=is_enabled, enable=enable, disable=disable) - service.notify_enabled(None, True) app.enable() diff --git a/plinth/modules/ejabberd/__init__.py b/plinth/modules/ejabberd/__init__.py index 7d73857a6..ba2a36575 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.firewall.components import Firewall from plinth.signals import (domainname_change, post_hostname_change, pre_hostname_change) from plinth.utils import format_lazy @@ -94,6 +95,11 @@ class EjabberdApp(app_module.App): login_required=True) self.add(shortcut) + firewall = Firewall('firewall-ejabberd', name, + ports=['xmpp-client', 'xmpp-server', + 'xmpp-bosh'], is_external=True) + self.add(firewall) + def init(): """Initialize the ejabberd module""" @@ -103,11 +109,9 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service( - 'ejabberd', name, - ports=['xmpp-client', 'xmpp-server', - 'xmpp-bosh'], is_external=True, is_enabled=is_enabled, - enable=enable, disable=disable) + service = service_module.Service('ejabberd', name, + is_enabled=is_enabled, enable=enable, + disable=disable) if is_enabled(): app.set_enabled(True) @@ -127,12 +131,9 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'ejabberd', ['setup']) global service if service is None: - service = service_module.Service( - 'ejabberd', name, - ports=['xmpp-client', 'xmpp-server', - 'xmpp-bosh'], is_external=True, is_enabled=is_enabled, - enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) + service = service_module.Service('ejabberd', name, + is_enabled=is_enabled, enable=enable, + disable=disable) helper.call('post', app.enable) diff --git a/plinth/modules/firewall/__init__.py b/plinth/modules/firewall/__init__.py index 1076cfa5f..540f1c3dd 100644 --- a/plinth/modules/firewall/__init__.py +++ b/plinth/modules/firewall/__init__.py @@ -18,15 +18,11 @@ FreedomBox app to configure a firewall. """ -import logging - from django.utils.translation import ugettext_lazy as _ -import plinth.service as service_module from plinth import actions from plinth import app as app_module from plinth import cfg, menu -from plinth.signals import service_enabled from plinth.utils import Version, format_lazy from .manifest import backup @@ -49,8 +45,6 @@ description = [ manual_page = 'Firewall' -LOGGER = logging.getLogger(__name__) - _port_details = {} app = None @@ -73,8 +67,6 @@ def init(): app = FirewallApp() app.set_enabled(True) - service_enabled.connect(on_service_enabled) - def setup(helper, old_version=None): """Install and configure the module.""" @@ -139,51 +131,6 @@ def remove_service(port, zone): _run(['remove-service', port, '--zone', zone], superuser=True) -def on_service_enabled(sender, service_id, enabled, **kwargs): - """ - Enable/disable firewall ports when a service is - enabled/disabled. - """ - del sender # Unused - del kwargs # Unused - - internal_enabled_services = get_enabled_services(zone='internal') - external_enabled_services = get_enabled_services(zone='external') - - LOGGER.info('Service enabled - %s, %s', service_id, enabled) - service = service_module.services[service_id] - for port in service.ports: - if enabled: - if port not in internal_enabled_services: - add_service(port, zone='internal') - - if (service.is_external and port not in external_enabled_services): - add_service(port, zone='external') - else: - # service already configured. - pass - else: - if port in internal_enabled_services: - enabled_services_on_port = [ - service_.is_enabled() - for service_ in service_module.services.values() - if port in service_.ports - and service_id != service_.service_id - ] - if not any(enabled_services_on_port): - remove_service(port, zone='internal') - - if port in external_enabled_services: - enabled_services_on_port = [ - service_.is_enabled() - for service_ in service_module.services.values() - if port in service_.ports and - service_id != service_.service_id and service_.is_external - ] - if not any(enabled_services_on_port): - remove_service(port, zone='external') - - def _run(arguments, superuser=False): """Run an given command and raise exception if there was an error""" command = 'firewall' diff --git a/plinth/modules/firewall/components.py b/plinth/modules/firewall/components.py new file mode 100644 index 000000000..525a3f1d0 --- /dev/null +++ b/plinth/modules/firewall/components.py @@ -0,0 +1,106 @@ +# +# 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 firewall functionality. +""" + +import logging + +from plinth import app +from plinth.modules import firewall + +logger = logging.getLogger(__name__) + + +class Firewall(app.FollowerComponent): + """Component to open/close firewall ports for an app.""" + + _all_firewall_components = {} + + def __init__(self, component_id, name=None, ports=None, is_external=False): + """Initialize the firewall component.""" + super().__init__(component_id) + + if not ports: + ports = [] + + self.name = name + self.ports = ports + self.is_external = is_external + + self._all_firewall_components[component_id] = self + + @property + def ports_details(self): + """Retrieve details of ports associated with this component..""" + ports_details = [] + for port in self.ports: + ports_details.append({ + 'name': port, + 'details': firewall.get_port_details(port), + }) + + return ports_details + + @classmethod + def list(cls): + """Return a list of all firewall ports.""" + return cls._all_firewall_components.values() + + def enable(self): + """Open firewall ports when the component is enabled.""" + super().enable() + + internal_enabled_ports = firewall.get_enabled_services(zone='internal') + external_enabled_ports = firewall.get_enabled_services(zone='external') + + logger.info('Firewall ports opened - %s, %s', self.name, self.ports) + for port in self.ports: + if port not in internal_enabled_ports: + firewall.add_service(port, zone='internal') + + if (self.is_external and port not in external_enabled_ports): + firewall.add_service(port, zone='external') + + def disable(self): + """Close firewall ports when the component is disabled.""" + super().disable() + + internal_enabled_ports = firewall.get_enabled_services(zone='internal') + external_enabled_ports = firewall.get_enabled_services(zone='external') + + logger.info('Firewall ports closed - %s, %s', self.name, self.ports) + for port in self.ports: + if port in internal_enabled_ports: + enabled_components_on_port = [ + component.is_enabled() + for component in self._all_firewall_components.values() + if port in component.ports + and self.component_id != component.component_id + ] + if not any(enabled_components_on_port): + firewall.remove_service(port, zone='internal') + + if port in external_enabled_ports: + enabled_components_on_port = [ + component.is_enabled() + for component in self._all_firewall_components.values() + if port in component.ports and self.component_id != + component.component_id and component.is_external + ] + if not any(enabled_components_on_port): + firewall.remove_service(port, zone='external') diff --git a/plinth/modules/firewall/templates/firewall.html b/plinth/modules/firewall/templates/firewall.html index 7d0d9abe8..b5ee99a8e 100644 --- a/plinth/modules/firewall/templates/firewall.html +++ b/plinth/modules/firewall/templates/firewall.html @@ -46,19 +46,19 @@ - {% for service in services|dictsort:"name" %} - {% if service.ports %} + {% for component in components|dictsort:"name" %} + {% if component.ports %}
- {{ service.name }} + {{ component.name }} - {% if service.is_enabled %} + {% if component.is_enabled %} {% trans "Enabled" %} {% else %} @@ -67,19 +67,19 @@ {% endif %} - {% for port in service.ports_details %} - {{ port.name }} ({{ port.details }}) - {% if port.name in internal_enabled_services and port.name in external_enabled_services %} + {% if port.name in internal_enabled_ports and port.name in external_enabled_ports %} {% trans "Permitted" %} - {% elif port.name in internal_enabled_services %} + {% elif port.name in internal_enabled_ports %} {% trans "Permitted (internal only)" %} - {% elif port.name in external_enabled_services %} + {% elif port.name in external_enabled_ports %} {% trans "Permitted (external only)" %} {% else %} diff --git a/plinth/modules/firewall/tests/test_components.py b/plinth/modules/firewall/tests/test_components.py new file mode 100644 index 000000000..88f571b37 --- /dev/null +++ b/plinth/modules/firewall/tests/test_components.py @@ -0,0 +1,139 @@ +# +# 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 . +# +""" +Tests for firewall app component. +""" + +from unittest.mock import call, patch + +import pytest + +from plinth.modules.firewall.components import Firewall + + +@pytest.fixture(name='empty_firewall_list', autouse=True) +def fixture_empty_firewall_list(): + """Remove all entries in firewall list before starting a test.""" + Firewall._all_firewall_components = {} + + +def test_init_without_arguments(): + """Test initializing the component without arguments.""" + with pytest.raises(ValueError): + Firewall(None) + + firewall = Firewall('test-component') + assert firewall.component_id == 'test-component' + assert firewall.name is None + assert firewall.ports == [] + assert not firewall.is_external + assert len(Firewall._all_firewall_components.items()) == 1 + assert Firewall._all_firewall_components['test-component'] == firewall + + +def test_init(): + """Test initializing the component.""" + firewall = Firewall('test-component', 'test-name', + ['test-port1', 'test-port2'], is_external=True) + assert firewall.name == 'test-name' + assert firewall.ports == ['test-port1', 'test-port2'] + assert firewall.is_external + + +@patch('plinth.modules.firewall.get_port_details') +def test_port_details(get_port_details): + """Test retrieving port details for a firewall component.""" + return_values = {'test-port1': '1234/tcp', 'test-port2': '5678/udp'} + + def get_port_details_side_effect(port): + return return_values[port] + + get_port_details.side_effect = get_port_details_side_effect + firewall = Firewall('test-component', ports=['test-port1', 'test-port2']) + assert firewall.ports_details == [{ + 'name': 'test-port1', + 'details': '1234/tcp' + }, { + 'name': 'test-port2', + 'details': '5678/udp' + }] + + +@patch('plinth.modules.firewall.add_service') +@patch('plinth.modules.firewall.get_enabled_services') +def test_enable(get_enabled_services, add_service): + """Test enabling a firewall component.""" + + def get_enabled_services_side_effect(zone): + return {'internal': ['test-port1'], 'external': ['test-port2']}[zone] + + get_enabled_services.side_effect = get_enabled_services_side_effect + # Internal + firewall = Firewall('test-firewall-1', ports=['test-port1', 'test-port2'], + is_external=False) + firewall.enable() + calls = [call('test-port2', zone='internal')] + add_service.assert_has_calls(calls) + + # External + add_service.reset_mock() + firewall = Firewall('test-firewall-2', ports=['test-port1', 'test-port2'], + is_external=True) + firewall.enable() + calls = [ + call('test-port1', zone='external'), + call('test-port2', zone='internal') + ] + add_service.assert_has_calls(calls) + + +@patch('plinth.modules.firewall.remove_service') +@patch('plinth.modules.firewall.add_service') +@patch('plinth.modules.firewall.get_enabled_services') +def test_disable(get_enabled_services, add_service, remove_service): + """Test disabling a firewall component.""" + Firewall('firewall-1', ports=['test-port1'], is_external=False) + Firewall('firewall-2', ports=['test-port2'], is_external=False).enable() + Firewall('firewall-3', ports=['test-port4'], is_external=True) + Firewall('firewall-4', ports=['test-port5'], is_external=True).enable() + + def get_enabled_services_side_effect(zone): + return { + 'internal': ['test-port1', 'test-port2'], + 'external': ['test-port4', 'test-port5'] + }[zone] + + get_enabled_services.side_effect = get_enabled_services_side_effect + all_ports = [ + 'test-port1', 'test-port2', 'test-port3', 'test-port4', 'test-port5', + 'test-port6' + ] + # Internal + firewall = Firewall('test-firewall-1', ports=all_ports, is_external=False) + firewall.disable() + calls = [call('test-port1', zone='internal')] + remove_service.assert_has_calls(calls) + + # External + remove_service.reset_mock() + firewall = Firewall('test-firewall-2', ports=all_ports, is_external=True) + firewall.disable() + calls = [ + call('test-port1', zone='internal'), + call('test-port4', zone='external') + ] + remove_service.assert_has_calls(calls) diff --git a/plinth/modules/firewall/views.py b/plinth/modules/firewall/views.py index 5b9b33313..2e85e1f08 100644 --- a/plinth/modules/firewall/views.py +++ b/plinth/modules/firewall/views.py @@ -23,6 +23,8 @@ from django.template.response import TemplateResponse import plinth.service as service_module from plinth.modules import firewall +from . import components + def index(request): """Serve introduction page""" @@ -34,15 +36,15 @@ def index(request): 'firewall_status': 'not_running' }) - internal_enabled_services = firewall.get_enabled_services(zone='internal') - external_enabled_services = firewall.get_enabled_services(zone='external') + internal_enabled_ports = firewall.get_enabled_services(zone='internal') + external_enabled_ports = firewall.get_enabled_services(zone='external') return TemplateResponse( request, 'firewall.html', { 'title': firewall.name, 'description': firewall.description, - 'services': list(service_module.services.values()), + 'components': components.Firewall.list(), 'manual_page': firewall.manual_page, - 'internal_enabled_services': internal_enabled_services, - 'external_enabled_services': external_enabled_services + 'internal_enabled_ports': internal_enabled_ports, + 'external_enabled_ports': external_enabled_ports }) diff --git a/plinth/modules/i2p/__init__.py b/plinth/modules/i2p/__init__.py index 9dca9a227..0da020b22 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.firewall.components import Firewall from plinth.modules.i2p.resources import FAVORITES from plinth.modules.users import register_group @@ -57,7 +58,6 @@ clients = clients group = ('i2p', _('Manage I2P application')) service = None -proxies_service = None manual_page = 'I2P' @@ -92,6 +92,15 @@ class I2PApp(app_module.App): allowed_groups=[group[0]]) self.add(shortcut) + firewall = Firewall('firewall-i2p-web', name, ports=['http', 'https'], + is_external=True) + self.add(firewall) + + firewall = Firewall('firewall-i2p-proxies', name, + ports=tunnels_to_manage.values(), + is_external=False) + self.add(firewall) + def init(): """Intialize the module.""" @@ -99,18 +108,12 @@ def init(): app = I2PApp() register_group(group) - global service, proxies_service + global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, - disable=disable, - is_running=is_running) - proxies_service = service_module.Service( - 'i2p-proxies', name, ports=tunnels_to_manage.values(), - is_external=False, is_enabled=is_enabled, is_running=is_running) - + service = service_module.Service( + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) if is_enabled(): app.set_enabled(True) @@ -144,19 +147,12 @@ def setup(helper, old_version=None): '--value', '0.0.0.0' ]) helper.call('post', enable) - global service, proxies_service + global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, - disable=disable, - is_running=is_running) - proxies_service = service_module.Service( - 'i2p-proxies', name, ports=tunnels_to_manage.values(), - is_external=False, is_enabled=is_enabled, is_running=is_running) + service = service_module.Service( + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) - helper.call('post', service.notify_enabled, None, True) - helper.call('post', proxies_service.notify_enabled, None, True) helper.call('post', app.enable) diff --git a/plinth/modules/ikiwiki/__init__.py b/plinth/modules/ikiwiki/__init__.py index bbccae098..c33c83bfe 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.firewall.components import Firewall from plinth.modules.users import register_group from plinth.utils import format_lazy @@ -83,6 +84,10 @@ class IkiwikiApp(app_module.App): for site in sites: self.add_shortcut(site) + firewall = Firewall('firewall-ikiwiki', name, ports=['http', 'https'], + is_external=True) + self.add(firewall) + def add_shortcut(self, site): """Add an ikiwiki shortcut to frontpage.""" shortcut = frontpage.Shortcut('shortcut-ikiwiki-' + site, site, @@ -106,9 +111,9 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service( - 'ikiwiki', name, ports=['http', 'https'], is_external=True, - is_enabled=is_enabled, enable=enable, disable=disable) + service = service_module.Service('ikiwiki', name, + is_enabled=is_enabled, enable=enable, + disable=disable) if is_enabled(): app.set_enabled(True) @@ -119,10 +124,9 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'ikiwiki', ['setup']) global service if service is None: - service = service_module.Service( - 'ikiwiki', name, ports=['http', 'https'], is_external=True, - is_enabled=is_enabled, enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) + service = service_module.Service('ikiwiki', name, + is_enabled=is_enabled, enable=enable, + disable=disable) helper.call('post', app.enable) diff --git a/plinth/modules/infinoted/__init__.py b/plinth/modules/infinoted/__init__.py index 596594fd8..a0332a6f9 100644 --- a/plinth/modules/infinoted/__init__.py +++ b/plinth/modules/infinoted/__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.firewall.components import Firewall from plinth.utils import format_lazy from plinth.views import ServiceView @@ -76,6 +77,10 @@ class InfinotedApp(app_module.App): login_required=False) self.add(shortcut) + firewall = Firewall('firewall-infinoted', name, + ports=['infinoted-plinth'], is_external=True) + self.add(firewall) + def init(): """Initialize the infinoted module.""" @@ -85,9 +90,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'infinoted-plinth' - ], is_external=True, enable=enable, disable=disable) + service = service_module.Service(managed_services[0], name, + enable=enable, disable=disable) if service.is_enabled(): app.set_enabled(True) @@ -106,11 +110,9 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'infinoted', ['setup']) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'infinoted-plinth' - ], is_external=True, enable=enable, disable=disable) + service = service_module.Service(managed_services[0], name, + enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) helper.call('post', app.enable) diff --git a/plinth/modules/jsxc/__init__.py b/plinth/modules/jsxc/__init__.py index 3532b128e..50d3a300e 100644 --- a/plinth/modules/jsxc/__init__.py +++ b/plinth/modules/jsxc/__init__.py @@ -26,6 +26,7 @@ from django.utils.translation import ugettext_lazy as _ from plinth import app as app_module from plinth import frontpage, menu from plinth import service as service_module +from plinth.modules.firewall.components import Firewall from .manifest import backup, clients @@ -66,6 +67,10 @@ class JSXCApp(app_module.App): icon='jsxc', url=reverse_lazy('jsxc:jsxc'), clients=clients) self.add(shortcut) + firewall = Firewall('firewall-jsxc', name, ports=['http', 'https'], + is_external=True) + self.add(firewall) + def init(): """Initialize the JSXC module""" @@ -75,9 +80,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service( - 'jsxc', name, ports=['http', 'https'], is_external=True, - is_enabled=is_enabled, enable=enable, disable=disable) + service = service_module.Service('jsxc', name, is_enabled=is_enabled, + enable=enable, disable=disable) if is_enabled(): app.set_enabled(True) @@ -88,9 +92,8 @@ def setup(helper, old_version=None): global service if not service: - service = service_module.Service( - 'jsxc', name, ports=['http', 'https'], is_external=True, - is_enabled=is_enabled, enable=enable, disable=disable) + service = service_module.Service('jsxc', name, is_enabled=is_enabled, + enable=enable, disable=disable) helper.call('post', app.enable) diff --git a/plinth/modules/matrixsynapse/__init__.py b/plinth/modules/matrixsynapse/__init__.py index 7ced635d3..6e6981fe6 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.firewall.components import Firewall from .manifest import backup, clients @@ -91,6 +92,10 @@ class MatrixSynapseApp(app_module.App): login_required=True) self.add(shortcut) + firewall = Firewall('firewall-matrixsynapse', name, + ports=['matrix-synapse-plinth'], is_external=True) + self.add(firewall) + def init(): """Initialize the matrix-synapse module.""" @@ -100,9 +105,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service('matrix-synapse', name, ports=[ - 'matrix-synapse-plinth' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service('matrix-synapse', name, + is_enabled=is_enabled, enable=enable, disable=disable) if is_enabled(): app.set_enabled(True) @@ -113,14 +117,12 @@ def setup(helper, old_version=None): helper.install(managed_packages) global service if service is None: - service = service_module.Service('matrix-synapse', name, ports=[ - 'matrix-synapse-plinth' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service('matrix-synapse', name, + is_enabled=is_enabled, enable=enable, disable=disable) helper.call('post', actions.superuser_run, 'matrixsynapse', ['post-install']) - helper.call('post', service.notify_enabled, None, True) helper.call('post', app.enable) diff --git a/plinth/modules/mediawiki/__init__.py b/plinth/modules/mediawiki/__init__.py index 24636c9c5..836181901 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.firewall.components import Firewall from .manifest import backup, clients @@ -78,6 +79,10 @@ class MediaWikiApp(app_module.App): clients=clients, login_required=True) self.add(shortcut) + firewall = Firewall('firewall-mediawiki', name, + ports=['http', 'https'], is_external=True) + self.add(firewall) + class Shortcut(frontpage.Shortcut): """Frontpage shortcut for only logged users when in private mode.""" @@ -96,9 +101,9 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service( - 'mediawiki', name, ports=['http', 'https'], is_external=True, - is_enabled=is_enabled, enable=enable, disable=disable) + service = service_module.Service('mediawiki', name, + is_enabled=is_enabled, enable=enable, + disable=disable) if is_enabled(): app.set_enabled(True) @@ -111,16 +116,9 @@ def setup(helper, old_version=None): helper.call('enable', actions.superuser_run, 'mediawiki', ['enable']) global service if service is None: - service = service_module.Service( - 'mediawiki', - name, - is_external=True, - is_enabled=is_enabled, - enable=enable, - disable=disable, - ports=['http', 'https'], - ) - helper.call('post', service.notify_enabled, None, True) + service = service_module.Service('mediawiki', name, + is_enabled=is_enabled, enable=enable, + disable=disable) helper.call('post', app.enable) diff --git a/plinth/modules/minetest/__init__.py b/plinth/modules/minetest/__init__.py index 9f584332d..1dd3b62e8 100644 --- a/plinth/modules/minetest/__init__.py +++ b/plinth/modules/minetest/__init__.py @@ -26,6 +26,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.firewall.components import Firewall from plinth.utils import format_lazy from .manifest import backup, clients @@ -95,6 +96,10 @@ class MinetestApp(app_module.App): login_required=False) self.add(shortcut) + firewall = Firewall('firewall-minetest', name, + ports=['minetest-plinth'], is_external=True) + self.add(firewall) + def init(): """Initialize the module.""" @@ -104,9 +109,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'minetest-plinth' - ], is_external=True, enable=enable, disable=disable) + service = service_module.Service(managed_services[0], name, + enable=enable, disable=disable) if service.is_enabled(): app.set_enabled(True) @@ -116,10 +120,8 @@ def setup(helper, old_version=None): helper.install(managed_packages) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'minetest-plinth' - ], is_external=True, enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) + service = service_module.Service(managed_services[0], name, + enable=enable, disable=disable) helper.call('post', app.enable) diff --git a/plinth/modules/mldonkey/__init__.py b/plinth/modules/mldonkey/__init__.py index 62f175c94..b5acb80b6 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.firewall.components import Firewall from plinth.modules.users import register_group from plinth.utils import format_lazy @@ -82,6 +83,11 @@ 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) + self.add(firewall) + + def init(): """Initialize the MLDonkey module.""" @@ -92,11 +98,9 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, - disable=disable, - is_running=is_running) + service = service_module.Service( + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) if is_enabled(): app.set_enabled(True) @@ -109,12 +113,9 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'mldonkey', ['enable']) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, - disable=disable, - is_running=is_running) - helper.call('post', service.notify_enabled, None, True) + service = service_module.Service( + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) helper.call('post', app.enable) diff --git a/plinth/modules/mumble/__init__.py b/plinth/modules/mumble/__init__.py index 8897b659c..f014beeb0 100644 --- a/plinth/modules/mumble/__init__.py +++ b/plinth/modules/mumble/__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.firewall.components import Firewall from plinth.views import ServiceView from .manifest import backup, clients @@ -79,6 +80,10 @@ class MumbleApp(app_module.App): configure_url=reverse_lazy('mumble:index'), clients=clients) self.add(shortcut) + firewall = Firewall('firewall-mumble', name, ports=['mumble-plinth'], + is_external=True) + self.add(firewall) + def init(): """Intialize the Mumble module.""" @@ -88,9 +93,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'mumble-plinth' - ], is_external=True, enable=enable, disable=disable) + service = service_module.Service(managed_services[0], name, + enable=enable, disable=disable) if service.is_enabled(): app.set_enabled(True) @@ -110,10 +114,8 @@ def setup(helper, old_version=None): helper.install(managed_packages) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'mumble-plinth' - ], is_external=True, enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) + service = service_module.Service(managed_services[0], name, + enable=enable, disable=disable) helper.call('post', app.enable) diff --git a/plinth/modules/openvpn/__init__.py b/plinth/modules/openvpn/__init__.py index 7a035511c..b8c39fb00 100644 --- a/plinth/modules/openvpn/__init__.py +++ b/plinth/modules/openvpn/__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.firewall.components import Firewall from plinth.utils import format_lazy from .manifest import backup @@ -80,6 +81,10 @@ class OpenVPNApp(app_module.App): configure_url=reverse_lazy('openvpn:index'), login_required=True) self.add(shortcut) + firewall = Firewall('firewall-openvpn', name, ports=['openvpn'], + is_external=True) + self.add(firewall) + def init(): """Initialize the OpenVPN module.""" @@ -89,8 +94,7 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, - ports=['openvpn'], is_external=True) + service = service_module.Service(managed_services[0], name) if service.is_enabled() and is_setup(): app.set_enabled(True) @@ -103,7 +107,6 @@ def setup(helper, old_version=None): global service if service is None: service = service_module.Service(managed_services[0], name, - ports=['openvpn'], is_external=True, enable=enable, disable=disable) if service.is_enabled() and is_setup(): diff --git a/plinth/modules/openvpn/views.py b/plinth/modules/openvpn/views.py index 49b01ae85..f44ddd491 100644 --- a/plinth/modules/openvpn/views.py +++ b/plinth/modules/openvpn/views.py @@ -70,8 +70,6 @@ def index(request): @require_POST def setup(request): """Start the setup process.""" - openvpn.service.notify_enabled(None, True) - global setup_process if not openvpn.is_setup() and not setup_process: setup_process = actions.superuser_run('openvpn', ['setup'], diff --git a/plinth/modules/privoxy/__init__.py b/plinth/modules/privoxy/__init__.py index d920fa3e9..52cc19f90 100644 --- a/plinth/modules/privoxy/__init__.py +++ b/plinth/modules/privoxy/__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.firewall.components import Firewall from plinth.utils import format_lazy from plinth.views import ServiceView @@ -83,6 +84,10 @@ class PrivoxyApp(app_module.App): configure_url=reverse_lazy('privoxy:index'), login_required=True) self.add(shortcut) + firewall = Firewall('firewall-privoxy', name, ports=['privoxy'], + is_external=False) + self.add(firewall) + def init(): """Intialize the module.""" @@ -93,7 +98,6 @@ def init(): setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': service = service_module.Service(managed_services[0], name, - ports=['privoxy'], is_external=False, enable=enable, disable=disable) if service.is_enabled(): @@ -107,9 +111,7 @@ def setup(helper, old_version=None): global service if service is None: service = service_module.Service(managed_services[0], name, - ports=['privoxy'], is_external=False, enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) helper.call('post', app.enable) diff --git a/plinth/modules/quassel/__init__.py b/plinth/modules/quassel/__init__.py index d289d81b5..0c276aec4 100644 --- a/plinth/modules/quassel/__init__.py +++ b/plinth/modules/quassel/__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.firewall.components import Firewall from plinth.utils import format_lazy from plinth.views import ServiceView @@ -87,6 +88,10 @@ class QuasselApp(app_module.App): login_required=True) self.add(shortcut) + firewall = Firewall('firewall-quassel', name, + ports=['quassel-plinth'], is_external=True) + self.add(firewall) + def init(): """Initialize the quassel module.""" @@ -96,9 +101,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'quassel-plinth' - ], is_external=True, enable=enable, disable=disable) + service = service_module.Service(managed_services[0], name, + enable=enable, disable=disable) if service.is_enabled(): app.set_enabled(True) @@ -118,10 +122,8 @@ def setup(helper, old_version=None): helper.install(managed_packages) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'quassel-plinth' - ], is_external=True, enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) + service = service_module.Service(managed_services[0], name, + enable=enable, disable=disable) helper.call('post', app.enable) diff --git a/plinth/modules/radicale/__init__.py b/plinth/modules/radicale/__init__.py index 181f475df..e26d5bbb3 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.firewall.components import Firewall from plinth.utils import format_lazy from .manifest import backup, clients @@ -90,6 +91,10 @@ class RadicaleApp(app_module.App): clients=clients, login_required=True) self.add(shortcut) + firewall = Firewall('firewall-radicale', name, + ports=['http', 'https'], is_external=True) + self.add(firewall) + def init(): """Initialize the radicale module.""" @@ -99,11 +104,9 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, - disable=disable, - is_running=is_running) + service = service_module.Service( + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) if is_enabled(): app.set_enabled(True) @@ -137,12 +140,9 @@ def setup(helper, old_version=None): global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, - disable=disable, - is_running=is_running) - helper.call('post', service.notify_enabled, None, True) + service = service_module.Service( + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) helper.call('post', app.enable) diff --git a/plinth/modules/repro/__init__.py b/plinth/modules/repro/__init__.py index 8a7d17742..32d669903 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.firewall.components import Firewall from plinth.views import ServiceView from .manifest import backup, clients @@ -88,6 +89,11 @@ class ReproApp(app_module.App): login_required=True) self.add(shortcut) + firewall = Firewall('firewall-repro', name, + ports=['sip', 'sips', + 'rtp-plinth'], is_external=True) + self.add(firewall) + def init(): """Initialize the repro module.""" @@ -97,9 +103,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'sip', 'sips', 'rtp-plinth' - ], is_external=True, enable=enable, disable=disable) + service = service_module.Service(managed_services[0], name, + enable=enable, disable=disable) if service.is_enabled(): app.set_enabled(True) @@ -120,10 +125,8 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'repro', ['setup']) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'sip', 'sips', 'rtp-plinth' - ], is_external=True, enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) + service = service_module.Service(managed_services[0], name, + enable=enable, disable=disable) helper.call('post', app.enable) diff --git a/plinth/modules/restore/__init__.py b/plinth/modules/restore/__init__.py index 1af05bedb..52d065ffa 100644 --- a/plinth/modules/restore/__init__.py +++ b/plinth/modules/restore/__init__.py @@ -23,6 +23,7 @@ from django.utils.translation import ugettext_lazy as _ from plinth import app as app_module from plinth import cfg, menu from plinth import service as service_module +from plinth.modules.firewall.components import Firewall from plinth.utils import format_lazy from .manifest import clients @@ -69,6 +70,10 @@ class RestoreApp(app_module.App): parent_url_name='apps') self.add(menu_item) + firewall = Firewall('firewall-restore', name, ports=['http', 'https'], + is_external=True) + self.add(firewall) + def init(): """Initialize the reStore module.""" @@ -78,9 +83,7 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, - ports=['http', - 'https'], is_external=False) + service = service_module.Service(managed_services[0], name) def setup(helper, old_version=None): @@ -88,6 +91,4 @@ def setup(helper, old_version=None): helper.install(managed_packages) global service if service is None: - service = service_module.Service(managed_services[0], name, - ports=['http', - 'https'], is_external=False) + service = service_module.Service(managed_services[0], name) diff --git a/plinth/modules/roundcube/__init__.py b/plinth/modules/roundcube/__init__.py index 60785b7e3..17c06de51 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.firewall.components import Firewall from .manifest import backup, clients @@ -81,6 +82,10 @@ class RoundcubeApp(app_module.App): clients=clients, login_required=True) self.add(shortcut) + firewall = Firewall('firewall-roundcube', name, + ports=['http', 'https'], is_external=True) + self.add(firewall) + def init(): """Intialize the module.""" @@ -90,9 +95,9 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service( - 'roundcube', name, ports=['http', 'https'], is_external=True, - is_enabled=is_enabled, enable=enable, disable=disable) + service = service_module.Service('roundcube', name, + is_enabled=is_enabled, enable=enable, + disable=disable) if is_enabled(): app.set_enabled(True) @@ -105,9 +110,9 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'roundcube', ['setup']) global service if service is None: - service = service_module.Service( - 'roundcube', name, ports=['http', 'https'], is_external=True, - is_enabled=is_enabled, enable=enable, disable=disable) + service = service_module.Service('roundcube', name, + is_enabled=is_enabled, enable=enable, + disable=disable) helper.call('post', app.enable) diff --git a/plinth/modules/searx/__init__.py b/plinth/modules/searx/__init__.py index e3e5e9b97..bd97f8a9c 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.firewall.components import Firewall from plinth.modules.users import register_group from .manifest import PUBLIC_ACCESS_SETTING_FILE, backup, clients @@ -75,6 +76,10 @@ class SearxApp(app_module.App): allowed_groups=[group[0]]) self.add(shortcut) + firewall = Firewall('firewall-searx', name, ports=['http', 'https'], + is_external=True) + self.add(firewall) + def set_shortcut_login_required(self, login_required): """Change the login_required property of shortcut.""" shortcut = self.remove('shortcut-searx') @@ -91,9 +96,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service(managed_services[0], name, + is_enabled=is_enabled, enable=enable, disable=disable) if is_enabled(): @@ -113,9 +117,8 @@ def setup(helper, old_version=None): global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service(managed_services[0], name, + is_enabled=is_enabled, enable=enable, disable=disable) helper.call('post', app.enable) diff --git a/plinth/modules/shaarli/__init__.py b/plinth/modules/shaarli/__init__.py index d2e30c59b..7e0068c31 100644 --- a/plinth/modules/shaarli/__init__.py +++ b/plinth/modules/shaarli/__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.firewall.components import Firewall from .manifest import clients @@ -69,6 +70,10 @@ class ShaarliApp(app_module.App): clients=clients, login_required=True) self.add(shortcut) + firewall = Firewall('firewall-shaarli', name, ports=['http', 'https'], + is_external=True) + self.add(firewall) + def init(): """Initialize the module.""" @@ -78,9 +83,9 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service( - 'shaarli', name, ports=['http', 'https'], is_external=True, - is_enabled=is_enabled, enable=enable, disable=disable) + service = service_module.Service('shaarli', name, + is_enabled=is_enabled, enable=enable, + disable=disable) if is_enabled(): app.set_enabled(True) @@ -91,10 +96,9 @@ def setup(helper, old_version=None): helper.install(managed_packages) global service if service is None: - service = service_module.Service( - 'shaarli', name, ports=['http', 'https'], is_external=True, - is_enabled=is_enabled, enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) + service = service_module.Service('shaarli', name, + is_enabled=is_enabled, enable=enable, + disable=disable) helper.call('post', app.enable) diff --git a/plinth/modules/shadowsocks/__init__.py b/plinth/modules/shadowsocks/__init__.py index 6ec65a5ce..66b343cde 100644 --- a/plinth/modules/shadowsocks/__init__.py +++ b/plinth/modules/shadowsocks/__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.firewall.components import Firewall from plinth.utils import format_lazy from .manifest import backup @@ -78,6 +79,11 @@ class ShadowsocksApp(app_module.App): login_required=True) self.add(shortcut) + firewall = Firewall('firewall-shadowsocks', name, + ports=['shadowsocks-local-plinth'], + is_external=False) + self.add(firewall) + def init(): """Intialize the module.""" @@ -87,10 +93,9 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service('shadowsocks', name, ports=[ - 'shadowsocks-local-plinth' - ], is_external=False, is_enabled=is_enabled, is_running=is_running, - enable=enable, disable=disable) + service = service_module.Service( + 'shadowsocks', name, is_enabled=is_enabled, is_running=is_running, + enable=enable, disable=disable) if service.is_enabled(): app.set_enabled(True) @@ -102,10 +107,9 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'shadowsocks', ['setup']) global service if service is None: - service = service_module.Service('shadowsocks', name, ports=[ - 'shadowsocks-local-plinth' - ], is_external=False, is_enabled=is_enabled, is_running=is_running, - enable=enable, disable=disable) + service = service_module.Service( + 'shadowsocks', name, is_enabled=is_enabled, is_running=is_running, + enable=enable, disable=disable) helper.call('post', app.enable) diff --git a/plinth/modules/ssh/__init__.py b/plinth/modules/ssh/__init__.py index b876b2985..a524ec1b4 100644 --- a/plinth/modules/ssh/__init__.py +++ b/plinth/modules/ssh/__init__.py @@ -22,8 +22,9 @@ from django.utils.translation import ugettext_lazy as _ from plinth import actions from plinth import app as app_module -from plinth import cfg, menu +from plinth import menu from plinth import service as service_module +from plinth.modules.firewall.components import Firewall from plinth.views import ServiceView from .manifest import backup @@ -62,6 +63,10 @@ class SSHApp(app_module.App): 'ssh:index', parent_url_name='system') self.add(menu_item) + firewall = Firewall('firewall-ssh', name, ports=['ssh'], + is_external=True) + self.add(firewall) + def init(): """Intialize the ssh module.""" @@ -70,8 +75,7 @@ def init(): app.set_enabled(True) global service - service = service_module.Service(managed_services[0], name, ports=['ssh'], - is_external=True) + service = service_module.Service(managed_services[0], name) def setup(helper, old_version=None): diff --git a/plinth/modules/storage/__init__.py b/plinth/modules/storage/__init__.py index 653af48f7..1e80cc714 100644 --- a/plinth/modules/storage/__init__.py +++ b/plinth/modules/storage/__init__.py @@ -298,10 +298,8 @@ def setup(helper, old_version=None): global service if service is None: service = service_module.Service( - managed_services[0], name, ports=[], is_external=True, - is_enabled=is_enabled, enable=enable, disable=disable, - is_running=is_running) - helper.call('post', service.notify_enabled, None, True) + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) disks = get_disks() root_device = get_root_device(disks) if is_expandable(root_device): diff --git a/plinth/modules/syncthing/__init__.py b/plinth/modules/syncthing/__init__.py index f5a1b61ab..6df1add5a 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.firewall.components import Firewall from plinth.modules.users import register_group from plinth.utils import format_lazy @@ -85,6 +86,10 @@ class SyncthingApp(app_module.App): login_required=True, allowed_groups=[group[0]]) self.add(shortcut) + firewall = Firewall('firewall-syncthing', name, + ports=['http', 'https'], is_external=True) + self.add(firewall) + def init(): """Intialize the module.""" @@ -95,11 +100,9 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, - disable=disable, - is_running=is_running) + service = service_module.Service( + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) if is_enabled(): app.set_enabled(True) @@ -111,12 +114,9 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'syncthing', ['enable']) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, - disable=disable, - is_running=is_running) - helper.call('post', service.notify_enabled, None, True) + service = service_module.Service( + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) helper.call('post', app.enable) diff --git a/plinth/modules/tahoe/__init__.py b/plinth/modules/tahoe/__init__.py index 4f1acdbe7..b3c8cbce9 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.firewall.components import Firewall from plinth.utils import format_lazy from .errors import TahoeConfigurationError @@ -77,6 +78,10 @@ class TahoeApp(app_module.App): icon='tahoe-lafs', url=None, login_required=True) self.add(shortcut) + firewall = Firewall('firewall-tahoe', name, ports=['tahoe-plinth'], + is_external=True) + self.add(firewall) + class Shortcut(frontpage.Shortcut): """Frontpage shortcut to use configured domain name for URL.""" @@ -123,11 +128,9 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup' and is_setup(): - service = service_module.Service(managed_services[0], name, ports=[ - 'tahoe-plinth' - ], is_external=True, is_enabled=is_enabled, enable=enable, - disable=disable, - is_running=is_running) + service = service_module.Service( + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) if is_enabled(): app.set_enabled(True) @@ -151,12 +154,9 @@ def post_setup(configured_domain_name): global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'tahoe-plinth' - ], is_external=True, is_enabled=is_enabled, enable=enable, - disable=disable, - is_running=is_running) - service.notify_enabled(None, True) + service = service_module.Service( + managed_services[0], name, is_enabled=is_enabled, enable=enable, + disable=disable, is_running=is_running) app.enable() diff --git a/plinth/modules/tor/__init__.py b/plinth/modules/tor/__init__.py index 376eff7d2..34a9b7f77 100644 --- a/plinth/modules/tor/__init__.py +++ b/plinth/modules/tor/__init__.py @@ -26,6 +26,7 @@ from plinth import action_utils, actions from plinth import app as app_module from plinth import menu from plinth import service as service_module +from plinth.modules.firewall.components import Firewall from plinth.modules.names import SERVICES from plinth.signals import domain_added, domain_removed @@ -75,6 +76,15 @@ class TorApp(app_module.App): 'tor:index', parent_url_name='apps') self.add(menu_item) + firewall = Firewall('firewall-tor-socks', _('Tor Socks Proxy'), + ports=['tor-socks'], is_external=False) + self.add(firewall) + + firewall = Firewall('firewall-tor-relay', _('Tor Bridge Relay'), + ports=['tor-orport', 'tor-obfs3', + 'tor-obfs4'], is_external=True) + self.add(firewall) + def init(): """Initialize the module.""" @@ -90,15 +100,14 @@ def init(): global socks_service socks_service = service_module.Service( - 'tor-socks', _('Tor Socks Proxy'), ports=['tor-socks'], - is_external=False, is_enabled=utils.is_enabled, + 'tor-socks', _('Tor Socks Proxy'), is_enabled=utils.is_enabled, is_running=utils.is_running) global bridge_service - bridge_service = service_module.Service( - 'tor-bridge', _('Tor Bridge Relay'), - ports=['tor-orport', 'tor-obfs3', 'tor-obfs4'], is_external=True, - is_enabled=utils.is_enabled, is_running=utils.is_running) + bridge_service = service_module.Service('tor-bridge', + _('Tor Bridge Relay'), + is_enabled=utils.is_enabled, + is_running=utils.is_running) # Register hidden service name with Name Services module. status = utils.get_status() @@ -132,23 +141,17 @@ def setup(helper, old_version=None): global socks_service if socks_service is None: - socks_service = service_module.Service( - 'tor-socks', _('Tor Anonymity Network'), ports=['tor-socks'], - is_external=False, is_enabled=utils.is_enabled, - is_running=utils.is_running) - - if not old_version: - helper.call('post', socks_service.notify_enabled, None, True) + socks_service = service_module.Service('tor-socks', + _('Tor Anonymity Network'), + is_enabled=utils.is_enabled, + is_running=utils.is_running) global bridge_service if bridge_service is None: - bridge_service = service_module.Service( - 'tor-bridge', _('Tor Bridge Relay'), - ports=['tor-orport', 'tor-obfs3', 'tor-obfs4'], is_external=True, - is_enabled=utils.is_enabled, is_running=utils.is_running) - - if not old_version: - helper.call('post', bridge_service.notify_enabled, None, True) + bridge_service = service_module.Service('tor-bridge', + _('Tor Bridge Relay'), + is_enabled=utils.is_enabled, + is_running=utils.is_running) helper.call('post', update_hidden_service_domain) helper.call('post', app.enable) diff --git a/plinth/modules/tor/views.py b/plinth/modules/tor/views.py index 326b713e2..a6a3da4a0 100644 --- a/plinth/modules/tor/views.py +++ b/plinth/modules/tor/views.py @@ -160,8 +160,6 @@ def _collect_config_result(request): status = tor_utils.get_status() - tor.socks_service.notify_enabled(None, status['enabled']) - tor.bridge_service.notify_enabled(None, status['enabled']) tor.update_hidden_service_domain(status) if not return_code: diff --git a/plinth/modules/transmission/__init__.py b/plinth/modules/transmission/__init__.py index 1778d546a..4638ab5db 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.firewall.components import Firewall from plinth.modules.users import register_group from .manifest import backup, clients @@ -77,6 +78,10 @@ class TransmissionApp(app_module.App): login_required=True, allowed_groups=[group[0]]) self.add(shortcut) + firewall = Firewall('firewall-transmission', name, + ports=['http', 'https'], is_external=True) + self.add(firewall) + def init(): """Initialize the Transmission module.""" @@ -87,9 +92,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service(managed_services[0], name, + is_enabled=is_enabled, enable=enable, disable=disable) if is_enabled(): @@ -111,11 +115,9 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'transmission', ['enable']) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service(managed_services[0], name, + is_enabled=is_enabled, enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) helper.call('post', app.enable) diff --git a/plinth/modules/ttrss/__init__.py b/plinth/modules/ttrss/__init__.py index 0b6245b8b..558541119 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.firewall.components import Firewall from plinth.modules.users import register_group from plinth.utils import Version, format_lazy @@ -83,6 +84,10 @@ class TTRSSApp(app_module.App): allowed_groups=[group[0]]) self.add(shortcut) + firewall = Firewall('firewall-ttrss', name, ports=['http', 'https'], + is_external=True) + self.add(firewall) + def init(): """Intialize the module.""" @@ -93,9 +98,8 @@ def init(): global service setup_helper = globals()['setup_helper'] if setup_helper.get_state() != 'needs-setup': - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service(managed_services[0], name, + is_enabled=is_enabled, enable=enable, disable=disable) if is_enabled(): @@ -110,11 +114,9 @@ def setup(helper, old_version=None): helper.call('post', actions.superuser_run, 'ttrss', ['enable']) global service if service is None: - service = service_module.Service(managed_services[0], name, ports=[ - 'http', 'https' - ], is_external=True, is_enabled=is_enabled, enable=enable, + service = service_module.Service(managed_services[0], name, + is_enabled=is_enabled, enable=enable, disable=disable) - helper.call('post', service.notify_enabled, None, True) helper.call('post', app.enable) diff --git a/plinth/modules/upgrades/__init__.py b/plinth/modules/upgrades/__init__.py index b12876e4a..2d6d7becb 100644 --- a/plinth/modules/upgrades/__init__.py +++ b/plinth/modules/upgrades/__init__.py @@ -64,7 +64,7 @@ def init(): app.set_enabled(True) global service - service = service_module.Service('auto-upgrades', name, is_external=False, + service = service_module.Service('auto-upgrades', name, is_enabled=is_enabled, enable=enable, disable=disable) diff --git a/plinth/service.py b/plinth/service.py index 3bd3cf82f..38b35e176 100644 --- a/plinth/service.py +++ b/plinth/service.py @@ -20,11 +20,7 @@ Framework for working with servers and their services. import collections -from django.utils.translation import ugettext_lazy as _ - -from plinth import action_utils, actions, cfg -from plinth.signals import service_enabled -from plinth.utils import format_lazy +from plinth import action_utils, actions services = {} @@ -32,8 +28,7 @@ services = {} class Service(): """ Representation of an application service provided by the machine - containing information such as current status and ports required - for operation. + containing information such as current status. - service_id: unique service name. If possible this should be the name of the service's systemd unit file (without the extension). @@ -44,18 +39,13 @@ class Service(): - is_running (optional): Boolean or a method returning Boolean """ - def __init__(self, service_id, name, ports=None, is_external=False, - is_enabled=None, enable=None, disable=None, is_running=None): - if ports is None: - ports = [] - + def __init__(self, service_id, name, is_enabled=None, enable=None, + disable=None, is_running=None): if is_enabled is None: is_enabled = self._default_is_enabled self.service_id = service_id self.name = name - self.ports = ports - self.is_external = is_external self._is_enabled = is_enabled self._enable = enable self._disable = disable @@ -65,32 +55,17 @@ class Service(): assert service_id not in services services[service_id] = self - @property - def ports_details(self): - """Retrieve details of ports associated with service.""" - from plinth.modules import firewall - ports_details = [] - for port in self.ports: - ports_details.append({ - 'name': port, - 'details': firewall.get_port_details(port), - }) - - return ports_details - def enable(self): if self._enable is None: actions.superuser_run('service', ['enable', self.service_id]) else: self._call_or_return(self._enable) - self.notify_enabled(None, True) def disable(self): if self._disable is None: actions.superuser_run('service', ['disable', self.service_id]) else: self._call_or_return(self._disable) - self.notify_enabled(None, False) def is_enabled(self): """Return whether the service is enabled.""" @@ -105,11 +80,6 @@ class Service(): return self._call_or_return(self._is_running) - def notify_enabled(self, sender, enabled): - """Notify observers about change in state of service.""" - service_enabled.send_robust(sender=sender, service_id=self.service_id, - enabled=enabled) - @staticmethod def _call_or_return(obj): """Calls obj if it's callable, returns it if it's Boolean.""" @@ -131,16 +101,3 @@ class Service(): """Returns a list of interfaces in a firewall zone.""" from plinth.modules import firewall return firewall.get_interfaces('internal') - - -def init(): - """Register some misc. services that don't fit elsewhere.""" - Service('http', _('Web Server'), ports=['http'], is_external=True, - is_enabled=True) - Service('https', _('Web Server over Secure Socket Layer'), ports=['https'], - is_external=True, is_enabled=True) - Service( - 'plinth', - format_lazy( - _('{box_name} Web Interface (Plinth)'), box_name=_(cfg.box_name)), - ports=['https'], is_external=True, is_enabled=True) diff --git a/plinth/signals.py b/plinth/signals.py index 6c8181c15..a64649c06 100644 --- a/plinth/signals.py +++ b/plinth/signals.py @@ -20,7 +20,6 @@ Django signals emitted within FreedomBox. from django.dispatch import Signal -service_enabled = Signal(providing_args=['service_id', 'enabled']) pre_module_loading = Signal() post_module_loading = Signal() post_setup = Signal(providing_args=['module_name']) diff --git a/plinth/tests/test_app.py b/plinth/tests/test_app.py index f714138cf..8a9bfd50e 100644 --- a/plinth/tests/test_app.py +++ b/plinth/tests/test_app.py @@ -153,6 +153,15 @@ def test_follower_component_initialization(): assert component.is_enabled() +def test_follower_component_set_enabled(): + """Test setting internal enabled state a follower component.""" + component = FollowerComponent('test-follower-1', False) + component.set_enabled(True) + assert component.is_enabled() + component.set_enabled(False) + assert not component.is_enabled() + + def test_follower_component_enable(): """Test enabling a follower component.""" component = FollowerComponent('test-follower-1', False)