From 2ebb565c926bcc6ae802ed4671a1752a47dc4da8 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Thu, 12 Dec 2019 00:00:35 -0500 Subject: [PATCH] diagnostics: Use new component based API for all diagnostic tests Signed-off-by: Sunil Mohan Adapa Reviewed-by: James Valleroy --- doc/dev/reference/app_module.rst | 15 --- doc/dev/tutorial/other.rst | 63 ++++------ plinth/modules/bind/__init__.py | 20 +--- plinth/modules/cockpit/__init__.py | 16 +-- plinth/modules/coquelicot/__init__.py | 16 +-- plinth/modules/datetime/__init__.py | 14 +-- plinth/modules/deluge/__init__.py | 20 +--- plinth/modules/diagnostics/__init__.py | 21 ++-- plinth/modules/diagnostics/diagnostics.py | 55 ++++----- .../diagnostics/templates/diagnostics.html | 8 +- ...stics_module.html => diagnostics_app.html} | 4 +- .../templates/diagnostics_button.html | 2 +- plinth/modules/diagnostics/urls.py | 4 +- plinth/modules/diaspora/__init__.py | 35 +++--- plinth/modules/ejabberd/__init__.py | 25 ++-- plinth/modules/gitweb/__init__.py | 18 +-- plinth/modules/i2p/__init__.py | 20 +--- plinth/modules/ikiwiki/__init__.py | 16 +-- plinth/modules/infinoted/__init__.py | 15 +-- plinth/modules/letsencrypt/__init__.py | 22 ++-- plinth/modules/matrixsynapse/__init__.py | 21 +--- plinth/modules/mediawiki/__init__.py | 15 +-- plinth/modules/minetest/__init__.py | 13 +- plinth/modules/minidlna/__init__.py | 15 +-- plinth/modules/mldonkey/__init__.py | 20 +--- plinth/modules/mumble/__init__.py | 18 +-- plinth/modules/networks/__init__.py | 37 +++--- plinth/modules/openvpn/__init__.py | 10 +- plinth/modules/privoxy/__init__.py | 22 ++-- plinth/modules/quassel/__init__.py | 15 +-- plinth/modules/radicale/__init__.py | 16 +-- plinth/modules/repro/__init__.py | 24 ++-- plinth/modules/roundcube/__init__.py | 16 +-- plinth/modules/samba/__init__.py | 28 ++--- plinth/modules/searx/__init__.py | 19 +-- plinth/modules/shadowsocks/__init__.py | 15 +-- plinth/modules/syncthing/__init__.py | 16 +-- plinth/modules/tahoe/__init__.py | 27 +++-- plinth/modules/tor/__init__.py | 112 +++++++++--------- plinth/modules/transmission/__init__.py | 31 ++--- plinth/modules/ttrss/__init__.py | 16 +-- plinth/modules/users/__init__.py | 33 +++--- plinth/templates/toolbar.html | 2 +- 43 files changed, 334 insertions(+), 616 deletions(-) rename plinth/modules/diagnostics/templates/{diagnostics_module.html => diagnostics_app.html} (87%) diff --git a/doc/dev/reference/app_module.rst b/doc/dev/reference/app_module.rst index 589b64481..de7be76f5 100644 --- a/doc/dev/reference/app_module.rst +++ b/doc/dev/reference/app_module.rst @@ -14,21 +14,6 @@ are loaded. The ``init()`` call order guarantees that other applications that this application depends on will be initialized before this application is initialized. -.diagnose() -^^^^^^^^^^^^^^^^^^^^^^^ - -Optional. Called when the user invokes system-wide diagnostics by visiting -**System -> Diagnositcs**. This method must return an array of diagnostic -results. Each diagnostic result must be a two-tuple with first element as a -string that is shown to the user as name of the test and second element is the -result of the test. It must be one of ``passed``, ``failed``, ``error``. Example -return value: - -.. code-block:: python3 - - [('Check http://localhost/app is reachable', 'passed'), - ('Check configuration is sane', 'passed')] - .depends ^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/dev/tutorial/other.rst b/doc/dev/tutorial/other.rst index 0d66bbb4b..da42cd9d2 100644 --- a/doc/dev/tutorial/other.rst +++ b/doc/dev/tutorial/other.rst @@ -102,57 +102,38 @@ daemons should be stopped during the backup process. In ``__init__.py``, add: Creating diagnostics ^^^^^^^^^^^^^^^^^^^^ -When the app does not work as expected, the user should known what is happening -with the app. The FreedomBox framework provides an API for running and showing -diagnostics results. The app has to implement a method for actually running the -diagnostics and return the results as a list. FreedomBox then takes care of +When the app does not work as expected, the user should know what is happening +with the app. FreedomBox framework provides an API for running and showing +diagnostics results. Most of the common diagnostic tests are implemented by the +framework as part of the components used by an app. FreedomBox takes care of calling the diagnostics method and displaying the list in a formatted manner. -To implement the diagnostics, a method called ``diagnose()`` has to be available -as ``.diagnose()``. It must return a list in which each item is the -result of a test performed. The item itself is a two-tuple containing the -display name of the test followed by the result as ``passed``, ``failed`` or -``error``. +To implement additional diagnostic tests on top of those provided by the +framework, the method :meth:`plinth.app.App.diagnose` has to be overridden or in +a component that belongs to the app, the method +:meth:`plinth.app.Component.diagnose` has to be overridden. The methods must +return a list in which each item is the result of a test performed. The item +itself is a two-tuple containing the display name of the test followed by the +result as ``passed``, ``failed`` or ``error``. .. code-block:: python3 - def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.extend(action_utils.diagnose_url_on_all( - 'https://{host}/transmission', extra_options=['--no-check-certificate'])) - - return results - -Now that we have implemented diagnostics, we also need to show a diagnostics -button in the App's page. Adding an attribute to the -:class:`~plinth.views.AppView` will take care of this. - -.. code-block:: python3 - - class TransmissionView(views.AppView): + class TransmissionAppView(views.AppView): ... - diagnostics_module_name = 'transmission' + def diagnose(): + """Run diagnostics and return the results.""" + results = super().diagnose() -There are several helpers available to implement some of the common diagnostic -tests. For our application we wish to implement a test to check whether the -``/transmission`` URL is accessible. Since this is a commonly performed test, -there is a helper method available and we have used it in the above code. The -``{host}`` tag replaced with various IP addresses, hostnames and domain names by -the helper to produce different kinds of URLs and they are all tested. Results -for all tests are returned which we then pass on to the framework. + results.append(['Example test', 'passed']) + + return results The user can trigger the diagnostics test by going to **System -> Diagnostics** page. This runs diagnostics for all the applications. Users can also run -diagnostics specifically for this app from the app's page. A diagnostics button -is shown by the `app.html` template automatically when -``diagnostics_module_name`` attribute is set in the app's ``AppView`` derived -from :obj:`plinth.views.AppView`. - -.. code-block:: django - - {% include "diagnostics_button.html" with module="ttrss" enabled=True %} +diagnostics specifically for this app from the app's page. A diagnostics menu +item is shown by the :class:`plinth.views.AppView` and `app.html` template +automatically when ``diagnose()`` method is overridden in the app or a +component. Logging ^^^^^^^ diff --git a/plinth/modules/bind/__init__.py b/plinth/modules/bind/__init__.py index 8e809456a..66e8b83d4 100644 --- a/plinth/modules/bind/__init__.py +++ b/plinth/modules/bind/__init__.py @@ -22,7 +22,7 @@ import re from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, menu from plinth.daemon import Daemon @@ -102,7 +102,11 @@ class BindApp(app_module.App): is_external=False) self.add(firewall) - daemon = Daemon('daemon-bind', managed_services[0]) + daemon = Daemon( + 'daemon-bind', managed_services[0], listen_ports=[(53, 'tcp6'), + (53, 'udp6'), + (53, 'tcp4'), + (53, 'udp4')]) self.add(daemon) @@ -129,18 +133,6 @@ def force_upgrade(helper, _packages): return True -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(53, 'tcp6')) - results.append(action_utils.diagnose_port_listening(53, 'udp6')) - results.append(action_utils.diagnose_port_listening(53, 'tcp4')) - results.append(action_utils.diagnose_port_listening(53, 'udp4')) - - return results - - def get_config(): """Get current configuration""" data = [line.strip() for line in open(CONFIG_FILE, 'r')] diff --git a/plinth/modules/cockpit/__init__.py b/plinth/modules/cockpit/__init__.py index e303f7761..df667496b 100644 --- a/plinth/modules/cockpit/__init__.py +++ b/plinth/modules/cockpit/__init__.py @@ -21,7 +21,7 @@ FreedomBox app to configure Cockpit. from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.daemon import Daemon @@ -93,7 +93,8 @@ class CockpitApp(app_module.App): is_external=True) self.add(firewall) - webserver = Webserver('webserver-cockpit', 'cockpit-freedombox') + webserver = Webserver('webserver-cockpit', 'cockpit-freedombox', + urls=['https://{host}/_cockpit/']) self.add(webserver) daemon = Daemon('daemon-cockpit', managed_services[0]) @@ -122,17 +123,6 @@ def setup(helper, old_version=None): helper.call('post', app.enable) -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.extend( - action_utils.diagnose_url_on_all('https://{host}/_cockpit/', - check_certificate=False)) - - return results - - def on_domain_added(sender, domain_type, name, description='', services=None, **kwargs): """Handle addition of a new domain.""" diff --git a/plinth/modules/coquelicot/__init__.py b/plinth/modules/coquelicot/__init__.py index bcc55c1a8..37878db47 100644 --- a/plinth/modules/coquelicot/__init__.py +++ b/plinth/modules/coquelicot/__init__.py @@ -20,7 +20,7 @@ Plinth module to configure coquelicot. from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import frontpage, menu from plinth.daemon import Daemon @@ -79,7 +79,8 @@ class CoquelicotApp(app_module.App): ports=['http', 'https'], is_external=True) self.add(firewall) - webserver = Webserver('webserver-coquelicot', 'coquelicot-freedombox') + webserver = Webserver('webserver-coquelicot', 'coquelicot-freedombox', + urls=['https://{host}/coquelicot']) self.add(webserver) daemon = Daemon('daemon-coquelicot', managed_services[0]) @@ -107,14 +108,3 @@ def get_current_max_file_size(): """Get the current value of maximum file size.""" size = actions.superuser_run('coquelicot', ['get-max-file-size']) return int(size.strip()) - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.extend( - action_utils.diagnose_url_on_all('https://{host}/coquelicot', - check_certificate=False)) - - return results diff --git a/plinth/modules/datetime/__init__.py b/plinth/modules/datetime/__init__.py index c23bc8b18..abce4f889 100644 --- a/plinth/modules/datetime/__init__.py +++ b/plinth/modules/datetime/__init__.py @@ -63,6 +63,12 @@ class DateTimeApp(app_module.App): daemon = Daemon('daemon-datetime', managed_services[0]) self.add(daemon) + def diagnose(self): + """Run diagnostics and return the results.""" + results = super().diagnose() + results.append(_diagnose_time_synchronized()) + return results + def init(): """Initialize the date/time module.""" @@ -77,14 +83,6 @@ def setup(helper, old_version=None): helper.call('post', app.enable) -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - results.append(_diagnose_time_synchronized()) - - return results - - def _diagnose_time_synchronized(): """Check whether time is synchronized to NTP server.""" result = 'failed' diff --git a/plinth/modules/deluge/__init__.py b/plinth/modules/deluge/__init__.py index e1aab2e4f..59c8f6e4c 100644 --- a/plinth/modules/deluge/__init__.py +++ b/plinth/modules/deluge/__init__.py @@ -20,7 +20,7 @@ FreedomBox app to configure a Deluge web client. from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import frontpage, menu from plinth.daemon import Daemon @@ -82,10 +82,12 @@ class DelugeApp(app_module.App): is_external=True) self.add(firewall) - webserver = Webserver('webserver-deluge', 'deluge-plinth') + webserver = Webserver('webserver-deluge', 'deluge-plinth', + urls=['https://{host}/deluge']) self.add(webserver) - daemon = Daemon('daemon-deluge', managed_services[0]) + daemon = Daemon('daemon-deluge', managed_services[0], + listen_ports=[(8112, 'tcp4')]) self.add(daemon) @@ -105,15 +107,3 @@ def setup(helper, old_version=None): helper.install(managed_packages) helper.call('post', actions.superuser_run, 'deluge', ['setup']) helper.call('post', app.enable) - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(8112, 'tcp4')) - results.extend( - action_utils.diagnose_url_on_all('https://{host}/deluge', - check_certificate=False)) - - return results diff --git a/plinth/modules/diagnostics/__init__.py b/plinth/modules/diagnostics/__init__.py index dfc228729..b74a66a8e 100644 --- a/plinth/modules/diagnostics/__init__.py +++ b/plinth/modules/diagnostics/__init__.py @@ -55,20 +55,19 @@ class DiagnosticsApp(app_module.App): 'diagnostics:index', parent_url_name='system') self.add(menu_item) + def diagnose(self): + """Run diagnostics and return the results.""" + results = super().diagnose() + results.append(action_utils.diagnose_port_listening(8000, 'tcp4')) + results.extend( + action_utils.diagnose_url_on_all('http://{host}/plinth/', + check_certificate=False)) + + return results + def init(): """Initialize the module""" global app app = DiagnosticsApp() app.set_enabled(True) - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - results.append(action_utils.diagnose_port_listening(8000, 'tcp4')) - results.extend( - action_utils.diagnose_url_on_all('http://{host}/plinth/', - check_certificate=False)) - - return results diff --git a/plinth/modules/diagnostics/diagnostics.py b/plinth/modules/diagnostics/diagnostics.py index 6bf0e8ec0..4eb1b3c45 100644 --- a/plinth/modules/diagnostics/diagnostics.py +++ b/plinth/modules/diagnostics/diagnostics.py @@ -19,6 +19,7 @@ FreedomBox app for running diagnostics. """ import collections +import importlib import logging import threading @@ -27,7 +28,7 @@ from django.template.response import TemplateResponse from django.utils.translation import ugettext_lazy as _ from django.views.decorators.http import require_POST -from plinth import module_loader +from plinth.app import App from plinth.modules import diagnostics logger = logging.Logger(__name__) @@ -53,23 +54,18 @@ def index(request): @require_POST -def module(request, module_name): - """Return diagnostics for a particular module.""" +def diagnose_app(request, app_id): + """Return diagnostics for a particular app.""" try: - module = module_loader.loaded_modules[module_name] + app = App.get(app_id) except KeyError: - raise Http404('Module does not exist or not loaded') + raise Http404('App does not exist') - results = [] - if hasattr(module, 'diagnose'): - results = module.diagnose() - - return TemplateResponse( - request, 'diagnostics_module.html', { - 'title': _('Diagnostic Test'), - 'module_name': module_name, - 'results': results - }) + return TemplateResponse(request, 'diagnostics_app.html', { + 'title': _('Diagnostic Test'), + 'app_id': app_id, + 'results': app.diagnose() + }) def _start_task(): @@ -99,29 +95,28 @@ def run_on_all_enabled_modules(): """Run diagnostics on all the enabled modules and store the result.""" global current_results current_results = { - 'modules': [], + 'apps': [], 'results': collections.OrderedDict(), 'progress_percentage': 0 } - modules = [] - for module_name, module in module_loader.loaded_modules.items(): - if not hasattr(module, 'diagnose'): - continue - - # Don't run setup on modules have not been setup yet. - # However, run on modules that need an upgrade. + apps = [] + for app in App.list(): + # XXX: Implement more cleanly. + # Don't run diagnostics on apps have not been setup yet. + # However, run on apps that need an upgrade. + module = importlib.import_module(app.__class__.__module__) if module.setup_helper.get_state() == 'needs-setup': continue - if not module.app.is_enabled(): + if not app.is_enabled(): continue - modules.append((module_name, module)) - current_results['results'][module_name] = None + apps.append((app.app_id, app)) + current_results['results'][app.app_id] = None - current_results['modules'] = modules - for current_index, (module_name, module) in enumerate(modules): - current_results['results'][module_name] = module.diagnose() + current_results['apps'] = apps + for current_index, (app_id, app) in enumerate(apps): + current_results['results'][app_id] = app.diagnose() current_results['progress_percentage'] = \ - int((current_index + 1) * 100 / len(modules)) + int((current_index + 1) * 100 / len(apps)) diff --git a/plinth/modules/diagnostics/templates/diagnostics.html b/plinth/modules/diagnostics/templates/diagnostics.html index 93809d582..a8474003e 100644 --- a/plinth/modules/diagnostics/templates/diagnostics.html +++ b/plinth/modules/diagnostics/templates/diagnostics.html @@ -63,11 +63,11 @@ {{ results.error }} {% else %} - {% for module, module_results in results.results.items %} -

{% blocktrans %}Module: {{ module }}{% endblocktrans %}

+ {% for app_id, app_results in results.results.items %} +

{% blocktrans %}App: {{ app_id }}{% endblocktrans %}

- {% if module_results %} - {% include "diagnostics_results.html" with results=module_results %} + {% if app_results %} + {% include "diagnostics_results.html" with results=app_results %} {% else %}

{% endif %} diff --git a/plinth/modules/diagnostics/templates/diagnostics_module.html b/plinth/modules/diagnostics/templates/diagnostics_app.html similarity index 87% rename from plinth/modules/diagnostics/templates/diagnostics_module.html rename to plinth/modules/diagnostics/templates/diagnostics_app.html index 6740fcdf6..540a65ae1 100644 --- a/plinth/modules/diagnostics/templates/diagnostics_module.html +++ b/plinth/modules/diagnostics/templates/diagnostics_app.html @@ -24,12 +24,12 @@

{% trans "Diagnostic Results" %}

-

{% blocktrans %}Module: {{ module_name }}{% endblocktrans %}

+

{% blocktrans %}App: {{ app_id }}{% endblocktrans %}

{% if results %} {% include "diagnostics_results.html" with results=results %} {% else %} -

{% trans "This module does not support diagnostics" %}

+

{% trans "This app does not support diagnostics" %}

{% endif %} {% endblock %} diff --git a/plinth/modules/diagnostics/templates/diagnostics_button.html b/plinth/modules/diagnostics/templates/diagnostics_button.html index e218daa3c..54aef9b75 100644 --- a/plinth/modules/diagnostics/templates/diagnostics_button.html +++ b/plinth/modules/diagnostics/templates/diagnostics_button.html @@ -20,7 +20,7 @@ {% load i18n %}
+ action="{% url 'diagnostics:app' app_id %}"> {% csrf_token %} {% if enabled %} diff --git a/plinth/modules/diagnostics/urls.py b/plinth/modules/diagnostics/urls.py index ace9382e3..055baa9dc 100644 --- a/plinth/modules/diagnostics/urls.py +++ b/plinth/modules/diagnostics/urls.py @@ -24,6 +24,6 @@ from . import diagnostics as views urlpatterns = [ url(r'^sys/diagnostics/$', views.index, name='index'), - url(r'^sys/diagnostics/(?P[1-9a-z\-]+)/$', views.module, - name='module'), + url(r'^sys/diagnostics/(?P[1-9a-z\-]+)/$', views.diagnose_app, + name='app'), ] diff --git a/plinth/modules/diaspora/__init__.py b/plinth/modules/diaspora/__init__.py index 4452a8627..fd166549f 100644 --- a/plinth/modules/diaspora/__init__.py +++ b/plinth/modules/diaspora/__init__.py @@ -105,6 +105,23 @@ class DiasporaApp(app_module.App): daemon = Daemon('daemon-diaspora', managed_services[0]) self.add(daemon) + def diagnose(self): + """Run diagnostics and return the results.""" + results = super().diagnose() + + results.append( + action_utils.diagnose_url('http://diaspora.localhost', kind='4', + check_certificate=False)) + results.append( + action_utils.diagnose_url('http://diaspora.localhost', kind='6', + check_certificate=False)) + results.append( + action_utils.diagnose_url( + 'http://diaspora.{}'.format(get_configured_domain_name()), + kind='4', check_certificate=False)) + + return results + class Shortcut(frontpage.Shortcut): """Frontpage shortcut to use configured domain name for URL.""" @@ -155,24 +172,6 @@ def disable_user_registrations(): actions.superuser_run('diaspora', ['disable-user-registrations']) -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append( - action_utils.diagnose_url('http://diaspora.localhost', kind='4', - check_certificate=False)) - results.append( - action_utils.diagnose_url('http://diaspora.localhost', kind='6', - check_certificate=False)) - results.append( - action_utils.diagnose_url( - 'http://diaspora.{}'.format(get_configured_domain_name()), - kind='4', check_certificate=False)) - - return results - - def generate_apache_configuration(conf_file, domain_name): """Generate Diaspora's apache configuration with the given domain name""" open(conf_file, 'w').close() diff --git a/plinth/modules/ejabberd/__init__.py b/plinth/modules/ejabberd/__init__.py index 29046027d..f92a05227 100644 --- a/plinth/modules/ejabberd/__init__.py +++ b/plinth/modules/ejabberd/__init__.py @@ -25,7 +25,7 @@ import pathlib from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.daemon import Daemon @@ -108,7 +108,8 @@ class EjabberdApp(app_module.App): 'xmpp-bosh'], is_external=True) self.add(firewall) - webserver = Webserver('webserver-ejabberd', 'jwchat-plinth') + webserver = Webserver('webserver-ejabberd', 'jwchat-plinth', + urls=['http://{host}/bosh/']) self.add(webserver) letsencrypt = LetsEncrypt( @@ -120,7 +121,10 @@ class EjabberdApp(app_module.App): managing_app='ejabberd') self.add(letsencrypt) - daemon = Daemon('daemon-ejabberd', managed_services[0]) + daemon = Daemon( + 'daemon-ejabberd', managed_services[0], + listen_ports=[(5222, 'tcp4'), (5222, 'tcp6'), (5269, 'tcp4'), + (5269, 'tcp6'), (5443, 'tcp4'), (5443, 'tcp6')]) self.add(daemon) @@ -214,18 +218,3 @@ def on_domain_added(sender, domain_type, name, description='', services=None, if name not in conf['domains']: actions.superuser_run('ejabberd', ['add-domain', '--domainname', name]) app.get_component('letsencrypt-ejabberd').setup_certificates() - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(5222, 'tcp4')) - results.append(action_utils.diagnose_port_listening(5222, 'tcp6')) - results.append(action_utils.diagnose_port_listening(5269, 'tcp4')) - results.append(action_utils.diagnose_port_listening(5269, 'tcp6')) - results.append(action_utils.diagnose_port_listening(5443, 'tcp4')) - results.append(action_utils.diagnose_port_listening(5443, 'tcp6')) - results.extend(action_utils.diagnose_url_on_all('http://{host}/bosh/')) - - return results diff --git a/plinth/modules/gitweb/__init__.py b/plinth/modules/gitweb/__init__.py index 57730a903..ed9b201f1 100644 --- a/plinth/modules/gitweb/__init__.py +++ b/plinth/modules/gitweb/__init__.py @@ -23,7 +23,7 @@ import os from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import frontpage, menu from plinth.errors import ActionError @@ -32,7 +32,8 @@ from plinth.modules.firewall.components import Firewall from plinth.modules.users import register_group from .forms import is_repo_url -from .manifest import GIT_REPO_PATH, backup, clients # noqa, pylint: disable=unused-import +from .manifest import (GIT_REPO_PATH, # noqa, pylint: disable=unused-import + backup, clients) clients = clients @@ -89,7 +90,8 @@ class GitwebApp(app_module.App): is_external=True) self.add(firewall) - webserver = Webserver('webserver-gitweb', 'gitweb-freedombox') + webserver = Webserver('webserver-gitweb', 'gitweb-freedombox', + urls=['https://{host}/gitweb/']) self.add(webserver) self.auth_webserver = GitwebWebserverAuth('webserver-gitweb-auth', @@ -191,16 +193,6 @@ def setup(helper, old_version=None): helper.call('post', app.enable) -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.extend( - action_utils.diagnose_url_on_all('https://{host}/gitweb/', - check_certificate=False)) - return results - - def restore_post(packet): """Update access after restoration of backups.""" app.update_service_access() diff --git a/plinth/modules/i2p/__init__.py b/plinth/modules/i2p/__init__.py index 0ab5d430b..b5a4e5b74 100644 --- a/plinth/modules/i2p/__init__.py +++ b/plinth/modules/i2p/__init__.py @@ -20,7 +20,7 @@ FreedomBox app to configure I2P. from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import frontpage, menu from plinth.daemon import Daemon @@ -105,10 +105,12 @@ class I2PApp(app_module.App): is_external=False) self.add(firewall) - webserver = Webserver('webserver-i2p', 'i2p-freedombox') + webserver = Webserver('webserver-i2p', 'i2p-freedombox', + urls=['https://{host}/i2p/']) self.add(webserver) - daemon = Daemon('daemon-i2p', managed_services[0]) + daemon = Daemon('daemon-i2p', managed_services[0], + listen_ports=[(7657, 'tcp6')]) self.add(daemon) @@ -152,15 +154,3 @@ def setup(helper, old_version=None): '--value', '0.0.0.0' ]) helper.call('post', app.enable) - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(7657, 'tcp6')) - results.extend( - action_utils.diagnose_url_on_all('https://{host}/i2p/', - check_certificate=False)) - - return results diff --git a/plinth/modules/ikiwiki/__init__.py b/plinth/modules/ikiwiki/__init__.py index e4eaf2033..213a58c58 100644 --- a/plinth/modules/ikiwiki/__init__.py +++ b/plinth/modules/ikiwiki/__init__.py @@ -21,7 +21,7 @@ FreedomBox app to configure ikiwiki. from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.modules.apache.components import Webserver @@ -85,7 +85,8 @@ class IkiwikiApp(app_module.App): is_external=True) self.add(firewall) - webserver = Webserver('webserver-ikiwiki', 'ikiwiki-plinth') + webserver = Webserver('webserver-ikiwiki', 'ikiwiki-plinth', + urls=['https://{host}/ikiwiki']) self.add(webserver) def add_shortcut(self, site, title): @@ -129,14 +130,3 @@ def setup(helper, old_version=None): helper.install(managed_packages) helper.call('post', actions.superuser_run, 'ikiwiki', ['setup']) helper.call('post', app.enable) - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.extend( - action_utils.diagnose_url_on_all('https://{host}/ikiwiki', - check_certificate=False)) - - return results diff --git a/plinth/modules/infinoted/__init__.py b/plinth/modules/infinoted/__init__.py index 133b209e4..3d2e2d060 100644 --- a/plinth/modules/infinoted/__init__.py +++ b/plinth/modules/infinoted/__init__.py @@ -21,7 +21,7 @@ FreedomBox app for infinoted. from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.daemon import Daemon @@ -85,7 +85,8 @@ class InfinotedApp(app_module.App): ports=['infinoted-plinth'], is_external=True) self.add(firewall) - daemon = Daemon('daemon-infinoted', managed_services[0]) + daemon = Daemon('daemon-infinoted', managed_services[0], + listen_ports=[(6523, 'tcp4'), (6523, 'tcp6')]) self.add(daemon) @@ -114,13 +115,3 @@ def setup(helper, old_version=None): helper.install(managed_packages) helper.call('post', actions.superuser_run, 'infinoted', ['setup']) helper.call('post', app.enable) - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(6523, 'tcp4')) - results.append(action_utils.diagnose_port_listening(6523, 'tcp6')) - - return results diff --git a/plinth/modules/letsencrypt/__init__.py b/plinth/modules/letsencrypt/__init__.py index 23f60bdb4..bcec0d953 100644 --- a/plinth/modules/letsencrypt/__init__.py +++ b/plinth/modules/letsencrypt/__init__.py @@ -85,6 +85,17 @@ class LetsEncryptApp(app_module.App): parent_url_name='system') self.add(menu_item) + def diagnose(self): + """Run diagnostics and return the results.""" + results = super().diagnose() + + for domain in names.components.DomainName.list(): + if domain.domain_type.can_have_certificate: + results.append( + action_utils.diagnose_url('https://' + domain.name)) + + return results + def init(): """Initialize the module.""" @@ -106,17 +117,6 @@ def setup(helper, old_version=None): ['setup', '--old-version', str(old_version)]) -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - for domain in names.components.DomainName.list(): - if domain.domain_type.can_have_certificate: - results.append(action_utils.diagnose_url('https://' + domain.name)) - - return results - - def certificate_obtain(domain): """Obtain a certificate for a domain and notify handlers.""" actions.superuser_run('letsencrypt', ['obtain', '--domain', domain]) diff --git a/plinth/modules/matrixsynapse/__init__.py b/plinth/modules/matrixsynapse/__init__.py index 08ea2ebaa..f9ebbcee6 100644 --- a/plinth/modules/matrixsynapse/__init__.py +++ b/plinth/modules/matrixsynapse/__init__.py @@ -26,7 +26,7 @@ from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ from ruamel.yaml.util import load_yaml_guess_indent -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import frontpage, menu from plinth.daemon import Daemon @@ -104,7 +104,8 @@ class MatrixSynapseApp(app_module.App): self.add(firewall) webserver = Webserver('webserver-matrixsynapse', - 'matrix-synapse-plinth') + 'matrix-synapse-plinth', + urls=['https://{host}/_matrix/client/versions']) self.add(webserver) letsencrypt = LetsEncrypt( @@ -116,7 +117,8 @@ class MatrixSynapseApp(app_module.App): managing_app='matrixsynapse') self.add(letsencrypt) - daemon = Daemon('daemon-matrixsynapse', managed_services[0]) + daemon = Daemon('daemon-matrixsynapse', managed_services[0], + listen_ports=[(8008, 'tcp4'), (8448, 'tcp4')]) self.add(daemon) @@ -152,19 +154,6 @@ def is_setup(): return os.path.exists(SERVER_NAME_PATH) -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(8008, 'tcp4')) - results.append(action_utils.diagnose_port_listening(8448, 'tcp4')) - results.extend( - action_utils.diagnose_url_on_all( - 'https://{host}/_matrix/client/versions', check_certificate=False)) - - return results - - def get_domains(): """Return a list of domains this app is interested in.""" domain = get_configured_domain_name() diff --git a/plinth/modules/mediawiki/__init__.py b/plinth/modules/mediawiki/__init__.py index e945cba0a..00a2bda31 100644 --- a/plinth/modules/mediawiki/__init__.py +++ b/plinth/modules/mediawiki/__init__.py @@ -20,7 +20,7 @@ FreedomBox app to configure MediaWiki. from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import frontpage, menu from plinth.daemon import Daemon @@ -88,7 +88,8 @@ class MediaWikiApp(app_module.App): ports=['http', 'https'], is_external=True) self.add(firewall) - webserver = Webserver('webserver-mediawiki', 'mediawiki') + webserver = Webserver('webserver-mediawiki', 'mediawiki', + urls=['https://{host}/mediawiki']) self.add(webserver) webserver = Webserver('webserver-mediawiki-freedombox', @@ -125,16 +126,6 @@ def setup(helper, old_version=None): helper.call('post', app.enable) -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.extend( - action_utils.diagnose_url_on_all('https://{host}/mediawiki', - check_certificate=False)) - return results - - def is_public_registration_enabled(): """Return whether public registration is enabled.""" output = actions.superuser_run('mediawiki', diff --git a/plinth/modules/minetest/__init__.py b/plinth/modules/minetest/__init__.py index ffa928ea4..8cebad289 100644 --- a/plinth/modules/minetest/__init__.py +++ b/plinth/modules/minetest/__init__.py @@ -22,7 +22,6 @@ import augeas from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.daemon import Daemon @@ -101,7 +100,8 @@ class MinetestApp(app_module.App): ports=['minetest-plinth'], is_external=True) self.add(firewall) - daemon = Daemon('daemon-minetest', managed_services[0]) + daemon = Daemon('daemon-minetest', managed_services[0], + listen_ports=[(30000, 'udp4')]) self.add(daemon) @@ -121,15 +121,6 @@ def setup(helper, old_version=None): helper.call('post', app.enable) -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(30000, 'udp4')) - - return results - - def load_augeas(): """Initialize Augeas.""" aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD + diff --git a/plinth/modules/minidlna/__init__.py b/plinth/modules/minidlna/__init__.py index 951e238dc..a969fe349 100644 --- a/plinth/modules/minidlna/__init__.py +++ b/plinth/modules/minidlna/__init__.py @@ -19,14 +19,12 @@ FreedomBox app to configure minidlna. """ from django.utils.translation import ugettext_lazy as _ -from plinth import actions import plinth.app as app_module -from plinth import frontpage, menu +from plinth import actions, frontpage, menu from plinth.daemon import Daemon from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall from plinth.modules.users import register_group -from plinth.action_utils import diagnose_url from .manifest import backup, clients # noqa @@ -77,7 +75,8 @@ class MiniDLNAApp(app_module.App): ) firewall = Firewall('firewall-minidlna', name, ports=['minidlna'], is_external=False) - webserver = Webserver('webserver-minidlna', 'minidlna-freedombox') + webserver = Webserver('webserver-minidlna', 'minidlna-freedombox', + urls=['http://localhost:8200/']) shortcut = frontpage.Shortcut( 'shortcut-minidlna', name, @@ -113,11 +112,3 @@ def setup(helper, old_version=None): helper.install(managed_packages) helper.call('post', actions.superuser_run, 'minidlna', ['setup']) helper.call('post', app.enable) - - -def diagnose(): - """Check if the http page listening on 8200 is accessible""" - results = [] - results.append(diagnose_url('http://localhost:8200/')) - - return results diff --git a/plinth/modules/mldonkey/__init__.py b/plinth/modules/mldonkey/__init__.py index 6c204756b..c12b86e41 100644 --- a/plinth/modules/mldonkey/__init__.py +++ b/plinth/modules/mldonkey/__init__.py @@ -20,7 +20,7 @@ FreedomBox app for mldonkey. from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.daemon import Daemon @@ -91,10 +91,12 @@ class MLDonkeyApp(app_module.App): is_external=True) self.add(firewall) - webserver = Webserver('webserver-mldonkey', 'mldonkey-freedombox') + webserver = Webserver('webserver-mldonkey', 'mldonkey-freedombox', + urls=['https://{host}/mldonkey/']) self.add(webserver) - daemon = Daemon('daemon-mldonkey', managed_services[0]) + daemon = Daemon('daemon-mldonkey', managed_services[0], + listen_ports=[(4080, 'tcp4')]) self.add(daemon) @@ -114,15 +116,3 @@ def setup(helper, old_version=None): helper.call('pre', actions.superuser_run, 'mldonkey', ['pre-install']) helper.install(managed_packages) helper.call('post', app.enable) - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(4080, 'tcp4')) - results.extend( - action_utils.diagnose_url_on_all('https://{host}/mldonkey/', - check_certificate=False)) - - return results diff --git a/plinth/modules/mumble/__init__.py b/plinth/modules/mumble/__init__.py index 565e6a478..57252f842 100644 --- a/plinth/modules/mumble/__init__.py +++ b/plinth/modules/mumble/__init__.py @@ -21,7 +21,6 @@ FreedomBox app to configure Mumble server. from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils from plinth import app as app_module from plinth import frontpage, menu from plinth.daemon import Daemon @@ -85,7 +84,10 @@ class MumbleApp(app_module.App): is_external=True) self.add(firewall) - daemon = Daemon('daemon-mumble', managed_services[0]) + daemon = Daemon( + 'daemon-mumble', managed_services[0], + listen_ports=[(64738, 'tcp4'), (64738, 'tcp6'), (64738, 'udp4'), + (64738, 'udp6')]) self.add(daemon) @@ -103,15 +105,3 @@ def setup(helper, old_version=None): """Install and configure the module.""" helper.install(managed_packages) helper.call('post', app.enable) - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(64738, 'tcp4')) - results.append(action_utils.diagnose_port_listening(64738, 'tcp6')) - results.append(action_utils.diagnose_port_listening(64738, 'udp4')) - results.append(action_utils.diagnose_port_listening(64738, 'udp6')) - - return results diff --git a/plinth/modules/networks/__init__.py b/plinth/modules/networks/__init__.py index 9a0d0816e..5a1fa58f1 100644 --- a/plinth/modules/networks/__init__.py +++ b/plinth/modules/networks/__init__.py @@ -61,6 +61,24 @@ class NetworksApp(app_module.App): 'networks:index', parent_url_name='system') self.add(menu_item) + def diagnose(self): + """Run diagnostics and return the results.""" + results = super().diagnose() + + interfaces = _get_shared_interfaces() + addresses = _get_interface_addresses(interfaces) + + for address in addresses: + results.append( + action_utils.diagnose_port_listening(53, 'tcp', address)) + results.append( + action_utils.diagnose_port_listening(53, 'udp', address)) + + results.append(_diagnose_dnssec('4')) + results.append(_diagnose_dnssec('6')) + + return results + def init(): """Initialize the Networks module.""" @@ -76,25 +94,6 @@ def setup(helper, old_version=None): helper.call('post', app.enable) -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - interfaces = _get_shared_interfaces() - addresses = _get_interface_addresses(interfaces) - - for address in addresses: - results.append(action_utils.diagnose_port_listening( - 53, 'tcp', address)) - results.append(action_utils.diagnose_port_listening( - 53, 'udp', address)) - - results.append(_diagnose_dnssec('4')) - results.append(_diagnose_dnssec('6')) - - return results - - def _get_shared_interfaces(): """Get active network interfaces in shared mode.""" shared_interfaces = [] diff --git a/plinth/modules/openvpn/__init__.py b/plinth/modules/openvpn/__init__.py index b2a57b862..bd9683d3a 100644 --- a/plinth/modules/openvpn/__init__.py +++ b/plinth/modules/openvpn/__init__.py @@ -21,7 +21,7 @@ FreedomBox app to configure OpenVPN server. from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.daemon import Daemon @@ -89,7 +89,8 @@ class OpenVPNApp(app_module.App): is_external=True) self.add(firewall) - daemon = Daemon('daemon-openvpn', managed_services[0]) + daemon = Daemon('daemon-openvpn', managed_services[0], + listen_ports=[(1194, 'udp4')]) self.add(daemon) @@ -115,8 +116,3 @@ def setup(helper, old_version=None): def is_setup(): """Return whether the service is running.""" return actions.superuser_run('openvpn', ['is-setup']).strip() == 'true' - - -def diagnose(): - """Run diagnostics and return the results.""" - return [action_utils.diagnose_port_listening(1194, 'udp4')] diff --git a/plinth/modules/privoxy/__init__.py b/plinth/modules/privoxy/__init__.py index 08c827bad..c2c91b353 100644 --- a/plinth/modules/privoxy/__init__.py +++ b/plinth/modules/privoxy/__init__.py @@ -90,9 +90,17 @@ class PrivoxyApp(app_module.App): is_external=False) self.add(firewall) - daemon = Daemon('daemon-privoxy', managed_services[0]) + daemon = Daemon('daemon-privoxy', managed_services[0], + listen_ports=[(8118, 'tcp4'), (8118, 'tcp6')]) self.add(daemon) + def diagnose(self): + """Run diagnostics and return the results.""" + results = super().diagnose() + results.append(action_utils.diagnose_url('https://www.debian.org')) + results.extend(diagnose_url_with_proxy()) + return results + def init(): """Initialize the module.""" @@ -120,18 +128,6 @@ class PrivoxyAppView(AppView): icon_filename = icon_filename -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(8118, 'tcp4')) - results.append(action_utils.diagnose_port_listening(8118, 'tcp6')) - results.append(action_utils.diagnose_url('https://www.debian.org')) - results.extend(diagnose_url_with_proxy()) - - return results - - def diagnose_url_with_proxy(): """Run a diagnostic on a URL with a proxy.""" url = 'https://debian.org/' # Gives a simple redirect to www. diff --git a/plinth/modules/quassel/__init__.py b/plinth/modules/quassel/__init__.py index 38115cfba..2b4401de8 100644 --- a/plinth/modules/quassel/__init__.py +++ b/plinth/modules/quassel/__init__.py @@ -23,7 +23,7 @@ import pathlib from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.daemon import Daemon @@ -108,7 +108,8 @@ class QuasselApp(app_module.App): managing_app='quassel') self.add(letsencrypt) - daemon = Daemon('daemon-quassel', managed_services[0]) + daemon = Daemon('daemon-quassel', managed_services[0], + listen_ports=[(4242, 'tcp4'), (4242, 'tcp6')]) self.add(daemon) @@ -129,16 +130,6 @@ def setup(helper, old_version=None): app.get_component('letsencrypt-quassel').setup_certificates() -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(4242, 'tcp4')) - results.append(action_utils.diagnose_port_listening(4242, 'tcp6')) - - return results - - def get_available_domains(): """Return an iterator with all domains able to have a certificate.""" return (domain.name for domain in names.components.DomainName.list() diff --git a/plinth/modules/radicale/__init__.py b/plinth/modules/radicale/__init__.py index d5bc72ca1..e8be8078e 100644 --- a/plinth/modules/radicale/__init__.py +++ b/plinth/modules/radicale/__init__.py @@ -26,7 +26,7 @@ import augeas from apt.cache import Cache from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.daemon import Daemon @@ -98,7 +98,8 @@ class RadicaleApp(app_module.App): is_external=True) self.add(firewall) - webserver = RadicaleWebserver('webserver-radicale', None) + webserver = RadicaleWebserver('webserver-radicale', None, + urls=['https://{host}/radicale']) self.add(webserver) uwsgi = RadicaleUwsgi('uwsgi-radicale', 'radicale') @@ -271,14 +272,3 @@ def get_rights_value(): value = 'owner_only' return value - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.extend( - action_utils.diagnose_url_on_all('https://{host}/radicale', - check_certificate=False)) - - return results diff --git a/plinth/modules/repro/__init__.py b/plinth/modules/repro/__init__.py index 853f2717e..96416cad4 100644 --- a/plinth/modules/repro/__init__.py +++ b/plinth/modules/repro/__init__.py @@ -21,7 +21,7 @@ FreedomBox app for repro. from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import frontpage, menu from plinth.daemon import Daemon @@ -98,7 +98,13 @@ class ReproApp(app_module.App): webserver = Webserver('webserver-repro', 'repro-plinth') self.add(webserver) - daemon = Daemon('daemon-repro', managed_services[0]) + daemon = Daemon( + 'daemon-repro', managed_services[0], listen_ports=[(5060, 'udp4'), + (5060, 'udp6'), + (5060, 'tcp4'), + (5060, 'tcp6'), + (5061, 'tcp4'), + (5061, 'tcp6')]) self.add(daemon) @@ -127,17 +133,3 @@ def setup(helper, old_version=None): helper.install(managed_packages) helper.call('post', actions.superuser_run, 'repro', ['setup']) helper.call('post', app.enable) - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(5060, 'udp4')) - results.append(action_utils.diagnose_port_listening(5060, 'udp6')) - results.append(action_utils.diagnose_port_listening(5060, 'tcp4')) - results.append(action_utils.diagnose_port_listening(5060, 'tcp6')) - results.append(action_utils.diagnose_port_listening(5061, 'tcp4')) - results.append(action_utils.diagnose_port_listening(5061, 'tcp6')) - - return results diff --git a/plinth/modules/roundcube/__init__.py b/plinth/modules/roundcube/__init__.py index fe27df7d3..b88102d6f 100644 --- a/plinth/modules/roundcube/__init__.py +++ b/plinth/modules/roundcube/__init__.py @@ -20,7 +20,7 @@ FreedomBox app to configure Roundcube. from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import frontpage, menu from plinth.modules.apache.components import Webserver @@ -88,7 +88,8 @@ class RoundcubeApp(app_module.App): ports=['http', 'https'], is_external=True) self.add(firewall) - webserver = Webserver('webserver-roundcube', 'roundcube') + webserver = Webserver('webserver-roundcube', 'roundcube', + urls=['https://{host}/roundcube']) self.add(webserver) @@ -108,14 +109,3 @@ def setup(helper, old_version=None): helper.install(managed_packages) helper.call('post', actions.superuser_run, 'roundcube', ['setup']) helper.call('post', app.enable) - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.extend( - action_utils.diagnose_url_on_all('https://{host}/roundcube', - check_certificate=False)) - - return results diff --git a/plinth/modules/samba/__init__.py b/plinth/modules/samba/__init__.py index b0b6d20ea..c93d5688f 100644 --- a/plinth/modules/samba/__init__.py +++ b/plinth/modules/samba/__init__.py @@ -27,12 +27,12 @@ import socket from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import frontpage, menu from plinth.daemon import Daemon -from plinth.modules.users import register_group from plinth.modules.firewall.components import Firewall +from plinth.modules.users import register_group from plinth.utils import format_lazy from .manifest import backup, clients # noqa, pylint: disable=unused-import @@ -94,10 +94,16 @@ class SambaApp(app_module.App): firewall = Firewall('firewall-samba', name, ports=['samba']) self.add(firewall) - daemon = Daemon('daemon-samba', managed_services[0]) + daemon = Daemon( + 'daemon-samba', managed_services[0], listen_ports=[(139, 'tcp4'), + (139, 'tcp6'), + (445, 'tcp4'), + (445, 'tcp6')]) self.add(daemon) - daemon_nmbd = Daemon('daemon-samba-nmbd', managed_services[1]) + daemon_nmbd = Daemon('daemon-samba-nmbd', managed_services[1], + listen_ports=[(137, 'udp4'), (138, 'udp4')]) + self.add(daemon_nmbd) @@ -119,20 +125,6 @@ def setup(helper, old_version=None): helper.call('post', app.enable) -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(137, 'udp4')) - results.append(action_utils.diagnose_port_listening(138, 'udp4')) - results.append(action_utils.diagnose_port_listening(139, 'tcp4')) - results.append(action_utils.diagnose_port_listening(139, 'tcp6')) - results.append(action_utils.diagnose_port_listening(445, 'tcp4')) - results.append(action_utils.diagnose_port_listening(445, 'tcp6')) - - return results - - def add_share(mount_point, share_type, filesystem): """Add a share.""" command = [ diff --git a/plinth/modules/searx/__init__.py b/plinth/modules/searx/__init__.py index 98bb00189..70c738ee4 100644 --- a/plinth/modules/searx/__init__.py +++ b/plinth/modules/searx/__init__.py @@ -22,14 +22,15 @@ import os from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import frontpage, menu from plinth.modules.apache.components import Uwsgi, Webserver from plinth.modules.firewall.components import Firewall from plinth.modules.users import register_group -from .manifest import PUBLIC_ACCESS_SETTING_FILE, backup, clients # noqa, pylint: disable=unused-import +from .manifest import (PUBLIC_ACCESS_SETTING_FILE, # noqa, pylint: disable=unused-import + backup, clients) clients = clients @@ -80,7 +81,8 @@ class SearxApp(app_module.App): is_external=True) self.add(firewall) - webserver = Webserver('webserver-searx', 'searx-freedombox') + webserver = Webserver('webserver-searx', 'searx-freedombox', + urls=['https://{host}/searx/']) self.add(webserver) webserver = SearxWebserverAuth('webserver-searx-auth', @@ -142,17 +144,6 @@ def is_public_access_enabled(): return os.path.exists(PUBLIC_ACCESS_SETTING_FILE) -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.extend( - action_utils.diagnose_url_on_all('https://{host}/searx/', - check_certificate=False)) - - return results - - def enable_public_access(): """Allow Searx app to be accessed by anyone with access.""" actions.superuser_run('searx', ['enable-public-access']) diff --git a/plinth/modules/shadowsocks/__init__.py b/plinth/modules/shadowsocks/__init__.py index 213388f51..5b31e0ffd 100644 --- a/plinth/modules/shadowsocks/__init__.py +++ b/plinth/modules/shadowsocks/__init__.py @@ -21,7 +21,7 @@ FreedomBox app to configure Shadowsocks. from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.daemon import Daemon @@ -86,7 +86,8 @@ class ShadowsocksApp(app_module.App): is_external=False) self.add(firewall) - daemon = Daemon('daemon-shadowsocks', managed_services[0]) + daemon = Daemon('daemon-shadowsocks', managed_services[0], + listen_ports=[(1080, 'tcp4'), (1080, 'tcp6')]) self.add(daemon) @@ -105,13 +106,3 @@ def setup(helper, old_version=None): helper.install(managed_packages) helper.call('post', actions.superuser_run, 'shadowsocks', ['setup']) helper.call('post', app.enable) - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(1080, 'tcp4')) - results.append(action_utils.diagnose_port_listening(1080, 'tcp6')) - - return results diff --git a/plinth/modules/syncthing/__init__.py b/plinth/modules/syncthing/__init__.py index ad7f1463b..ab6f29198 100644 --- a/plinth/modules/syncthing/__init__.py +++ b/plinth/modules/syncthing/__init__.py @@ -20,7 +20,7 @@ FreedomBox app to configure Syncthing. from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.daemon import Daemon @@ -95,7 +95,8 @@ class SyncthingApp(app_module.App): ports=['syncthing'], is_external=True) self.add(firewall) - webserver = Webserver('webserver-syncthing', 'syncthing-plinth') + webserver = Webserver('webserver-syncthing', 'syncthing-plinth', + urls=['https://{host}/syncthing/']) self.add(webserver) daemon = Daemon('daemon-syncthing', managed_services[0]) @@ -122,14 +123,3 @@ def setup(helper, old_version=None): if old_version == 1 and app.is_enabled(): app.get_component('firewall-syncthing-ports').enable() - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.extend( - action_utils.diagnose_url_on_all('https://{host}/syncthing/', - check_certificate=False)) - - return results diff --git a/plinth/modules/tahoe/__init__.py b/plinth/modules/tahoe/__init__.py index bae49c55d..fd11180bc 100644 --- a/plinth/modules/tahoe/__init__.py +++ b/plinth/modules/tahoe/__init__.py @@ -92,6 +92,20 @@ class TahoeApp(app_module.App): daemon = Daemon('daemon-tahoe', managed_services[0]) self.add(daemon) + def diagnose(self): + """Run diagnostics and return the results.""" + results = super().diagnose() + results.extend([ + action_utils.diagnose_url('http://localhost:5678', kind='4', + check_certificate=False), + action_utils.diagnose_url('http://localhost:5678', kind='6', + check_certificate=False), + action_utils.diagnose_url( + 'http://{}:5678'.format(get_configured_domain_name()), + kind='4', check_certificate=False) + ]) + return results + class Shortcut(frontpage.Shortcut): """Frontpage shortcut to use configured domain name for URL.""" @@ -157,19 +171,6 @@ def post_setup(configured_domain_name): app.enable() -def diagnose(): - """Run diagnostics and return the results.""" - return [ - action_utils.diagnose_url('http://localhost:5678', kind='4', - check_certificate=False), - action_utils.diagnose_url('http://localhost:5678', kind='6', - check_certificate=False), - action_utils.diagnose_url( - 'http://{}:5678'.format(get_configured_domain_name()), kind='4', - check_certificate=False) - ] - - def add_introducer(introducer): """Add an introducer to the storage node's list of introducers. Param introducer must be a tuple of (pet_name, furl) diff --git a/plinth/modules/tor/__init__.py b/plinth/modules/tor/__init__.py index 8551a0a61..fd6bfc9e0 100644 --- a/plinth/modules/tor/__init__.py +++ b/plinth/modules/tor/__init__.py @@ -92,9 +92,65 @@ class TorApp(app_module.App): 'tor-obfs4'], is_external=True) self.add(firewall) - daemon = Daemon('daemon-tor', managed_services[0], strict_check=True) + daemon = Daemon( + 'daemon-tor', managed_services[0], strict_check=True, + listen_ports=[(9050, 'tcp4'), (9050, 'tcp6'), (9040, 'tcp4'), + (9040, 'tcp6'), (9053, 'udp4'), (9053, 'udp6')]) self.add(daemon) + def diagnose(self): + """Run diagnostics and return the results.""" + results = super().diagnose() + + results.extend(_diagnose_control_port()) + + output = actions.superuser_run('tor', ['get-status']) + ports = json.loads(output)['ports'] + + results.append([ + _('Tor relay port available'), + 'passed' if 'orport' in ports else 'failed' + ]) + if 'orport' in ports: + results.append( + action_utils.diagnose_port_listening(int(ports['orport']), + 'tcp4')) + results.append( + action_utils.diagnose_port_listening(int(ports['orport']), + 'tcp6')) + + results.append([ + _('Obfs3 transport registered'), + 'passed' if 'obfs3' in ports else 'failed' + ]) + if 'obfs3' in ports: + results.append( + action_utils.diagnose_port_listening(int(ports['obfs3']), + 'tcp4')) + results.append( + action_utils.diagnose_port_listening(int(ports['obfs3']), + 'tcp6')) + + results.append([ + _('Obfs4 transport registered'), + 'passed' if 'obfs4' in ports else 'failed' + ]) + if 'obfs4' in ports: + results.append( + action_utils.diagnose_port_listening(int(ports['obfs4']), + 'tcp4')) + results.append( + action_utils.diagnose_port_listening(int(ports['obfs4']), + 'tcp6')) + + results.append(_diagnose_url_via_tor('http://www.debian.org', '4')) + results.append(_diagnose_url_via_tor('http://www.debian.org', '6')) + + results.append(_diagnose_tor_use('https://check.torproject.org', '4')) + results.append(_diagnose_tor_use('https://check.torproject.org', '6')) + + return results + def init(): """Initialize the module.""" @@ -148,60 +204,6 @@ def update_hidden_service_domain(status=None): name=status['hs_hostname'], services=services) -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - results.append(action_utils.diagnose_port_listening(9050, 'tcp4')) - results.append(action_utils.diagnose_port_listening(9050, 'tcp6')) - results.append(action_utils.diagnose_port_listening(9040, 'tcp4')) - results.append(action_utils.diagnose_port_listening(9040, 'tcp6')) - results.append(action_utils.diagnose_port_listening(9053, 'udp4')) - results.append(action_utils.diagnose_port_listening(9053, 'udp6')) - - results.extend(_diagnose_control_port()) - - output = actions.superuser_run('tor', ['get-status']) - ports = json.loads(output)['ports'] - - results.append([ - _('Tor relay port available'), - 'passed' if 'orport' in ports else 'failed' - ]) - if 'orport' in ports: - results.append( - action_utils.diagnose_port_listening(int(ports['orport']), 'tcp4')) - results.append( - action_utils.diagnose_port_listening(int(ports['orport']), 'tcp6')) - - results.append([ - _('Obfs3 transport registered'), - 'passed' if 'obfs3' in ports else 'failed' - ]) - if 'obfs3' in ports: - results.append( - action_utils.diagnose_port_listening(int(ports['obfs3']), 'tcp4')) - results.append( - action_utils.diagnose_port_listening(int(ports['obfs3']), 'tcp6')) - - results.append([ - _('Obfs4 transport registered'), - 'passed' if 'obfs4' in ports else 'failed' - ]) - if 'obfs4' in ports: - results.append( - action_utils.diagnose_port_listening(int(ports['obfs4']), 'tcp4')) - results.append( - action_utils.diagnose_port_listening(int(ports['obfs4']), 'tcp6')) - - results.append(_diagnose_url_via_tor('http://www.debian.org', '4')) - results.append(_diagnose_url_via_tor('http://www.debian.org', '6')) - - results.append(_diagnose_tor_use('https://check.torproject.org', '4')) - results.append(_diagnose_tor_use('https://check.torproject.org', '6')) - - return results - - def _diagnose_control_port(): """Diagnose whether Tor control port is open on 127.0.0.1 only.""" results = [] diff --git a/plinth/modules/transmission/__init__.py b/plinth/modules/transmission/__init__.py index 738c3c0c5..128e2fb34 100644 --- a/plinth/modules/transmission/__init__.py +++ b/plinth/modules/transmission/__init__.py @@ -22,13 +22,13 @@ import json from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import frontpage, menu from plinth.daemon import Daemon from plinth.modules.apache.components import Webserver from plinth.modules.firewall.components import Firewall -from plinth.modules.users import register_group, add_user_to_share_group +from plinth.modules.users import add_user_to_share_group, register_group from .manifest import backup, clients # noqa, pylint: disable=unused-import @@ -74,20 +74,23 @@ class TransmissionApp(app_module.App): parent_url_name='apps') self.add(menu_item) - shortcut = frontpage.Shortcut( - 'shortcut-transmission', name, short_description=short_description, - icon=icon_filename, url='/transmission', clients=clients, - login_required=True, allowed_groups=[group[0]]) + shortcut = frontpage.Shortcut('shortcut-transmission', name, + short_description=short_description, + icon=icon_filename, url='/transmission', + clients=clients, login_required=True, + allowed_groups=[group[0]]) self.add(shortcut) firewall = Firewall('firewall-transmission', name, ports=['http', 'https'], is_external=True) self.add(firewall) - webserver = Webserver('webserver-transmission', 'transmission-plinth') + webserver = Webserver('webserver-transmission', 'transmission-plinth', + urls=['https://{host}/transmission']) self.add(webserver) - daemon = Daemon('daemon-transmission', managed_services[0]) + daemon = Daemon('daemon-transmission', managed_services[0], + listen_ports=[(9091, 'tcp4')]) self.add(daemon) @@ -115,15 +118,3 @@ def setup(helper, old_version=None): input=json.dumps(new_configuration).encode()) add_user_to_share_group(reserved_usernames[0], managed_services[0]) helper.call('post', app.enable) - - -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(9091, 'tcp4')) - results.extend( - action_utils.diagnose_url_on_all('https://{host}/transmission', - check_certificate=False)) - - return results diff --git a/plinth/modules/ttrss/__init__.py b/plinth/modules/ttrss/__init__.py index 7b77faec6..14caf41d5 100644 --- a/plinth/modules/ttrss/__init__.py +++ b/plinth/modules/ttrss/__init__.py @@ -21,7 +21,7 @@ FreedomBox app to configure Tiny Tiny RSS. from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.daemon import Daemon @@ -92,7 +92,8 @@ class TTRSSApp(app_module.App): is_external=True) self.add(firewall) - webserver = Webserver('webserver-ttrss', 'tt-rss-plinth') + webserver = Webserver('webserver-ttrss', 'tt-rss-plinth', + urls=['https://{host}/tt-rss']) self.add(webserver) daemon = Daemon('daemon-ttrss', managed_services[0]) @@ -138,17 +139,6 @@ def force_upgrade(helper, packages): return True -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.extend( - action_utils.diagnose_url_on_all('https://{host}/tt-rss', - check_certificate=False)) - - return results - - def backup_pre(packet): """Save database contents.""" actions.superuser_run('ttrss', ['dump-database']) diff --git a/plinth/modules/users/__init__.py b/plinth/modules/users/__init__.py index 69deb9d8d..c27378769 100644 --- a/plinth/modules/users/__init__.py +++ b/plinth/modules/users/__init__.py @@ -23,9 +23,10 @@ import subprocess from django.utils.translation import ugettext_lazy as _ -from plinth import action_utils, actions +from plinth import actions from plinth import app as app_module from plinth import cfg, menu +from plinth.daemon import Daemon from plinth.utils import format_lazy version = 3 @@ -37,6 +38,8 @@ managed_packages = [ 'nslcd', 'samba-common-bin', 'slapd', 'tdb-tools' ] +managed_services = ['slapd'] + first_boot_steps = [ { 'id': 'users_firstboot', @@ -79,6 +82,20 @@ class UsersApp(app_module.App): 'users:index', parent_url_name='system') self.add(menu_item) + daemon = Daemon('daemon-users', managed_services[0], + listen_ports=[(389, 'tcp4'), (389, 'tcp6')]) + self.add(daemon) + + def diagnose(self): + """Run diagnostics and return the results.""" + results = super().diagnose() + + results.append(_diagnose_ldap_entry('dc=thisbox')) + results.append(_diagnose_ldap_entry('ou=people')) + results.append(_diagnose_ldap_entry('ou=groups')) + + return results + def init(): """Initialize the user module.""" @@ -96,20 +113,6 @@ def setup(helper, old_version=None): create_group('freedombox-share') -def diagnose(): - """Run diagnostics and return the results.""" - results = [] - - results.append(action_utils.diagnose_port_listening(389, 'tcp4')) - results.append(action_utils.diagnose_port_listening(389, 'tcp6')) - - results.append(_diagnose_ldap_entry('dc=thisbox')) - results.append(_diagnose_ldap_entry('ou=people')) - results.append(_diagnose_ldap_entry('ou=groups')) - - return results - - def _diagnose_ldap_entry(search_item): """Diagnose that an LDAP entry exists.""" result = 'failed' diff --git a/plinth/templates/toolbar.html b/plinth/templates/toolbar.html index 33514589e..cbd4947c9 100644 --- a/plinth/templates/toolbar.html +++ b/plinth/templates/toolbar.html @@ -61,7 +61,7 @@