diff --git a/actions/module-manager b/actions/module-manager deleted file mode 100755 index 275aba608..000000000 --- a/actions/module-manager +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/sh -# -# This file is part of Plinth. -# -# 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 . -# - -# Usage: -# module-manager list-available -# module-manager list-enabled -# module-manager enable -# module-manager disable - -# list of modules that may be enabled/disabled -modules="owncloud" - -case "$1" in -"list-available") - # TODO: Replace this with something like "aptitude search -F %p plinth-" - echo "$modules" - ;; - -"list-enabled") - # TODO: Replace this with something like 'aptitude search -F %p | grep "plinth-"' - for module in "$modules" - do - if [ -e "$2"/modules/enabled/"$module" ] ; then - echo "$module" - fi - done - ;; - -"enable") - # TODO: Replace this with "aptitude install plinth-" - for module in "$modules" - do - if [ "$3" = "$module" ] ; then - if [ ! -e "$2"/modules/enabled/"$3" ] ; then - touch "$2"/modules/enabled/"$3" - RETVAL=$? - if [ $RETVAL -eq 0 ] ; then - echo "enabled" "$3" - else - echo "failed to enable" "$3" - fi - exit $RETVAL - fi - fi - done - echo "failed to enable invalid module" "$3" - exit 1 - ;; - -"disable") - # TODO: Replace this with "aptitude purge plinth-" - for module in "$modules" - do - if [ "$3" = "$module" ] ; then - if [ -e "$2"/modules/enabled/"$3" ] ; then - rm -f "$2"/modules/enabled/"$3" - RETVAL=$? - if [ $RETVAL -eq 0 ] ; then - echo "disabled" "$3" - else - echo "failed to disable" "$3" - fi - exit $RETVAL - fi - fi - done - echo "failed to disable invalid module" "$3" - exit 1 - ;; -esac diff --git a/actions/pagekite b/actions/pagekite index 9bb1165b8..5169bcf29 100755 --- a/actions/pagekite +++ b/actions/pagekite @@ -25,7 +25,6 @@ import argparse import augeas import json import os -import subprocess from plinth import action_utils from plinth.modules.pagekite import utils diff --git a/actions/tor b/actions/tor index 22fab6238..d26b0bce4 100755 --- a/actions/tor +++ b/actions/tor @@ -22,11 +22,16 @@ Configuration helper for the Tor service """ import argparse +import codecs import os +import re +import socket from plinth import action_utils TOR_CONFIG = '/etc/tor/torrc' +TOR_STATE_FILE = '/var/lib/tor/state' +TOR_AUTH_COOKIE = '/var/run/tor/control.authcookie' def parse_arguments(): @@ -34,20 +39,12 @@ def parse_arguments(): parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(dest='subcommand', help='Sub command') - # Enable and start the service subparsers.add_parser('enable', help='Enable and start Tor service') - - # Disable and stop the service subparsers.add_parser('disable', help='Disable and stop Tor service') - - # Get currently configured Tor hidden service information subparsers.add_parser('get-hs', help='Get hidden service') - - # Enable Tor hidden service subparsers.add_parser('enable-hs', help='Enable hidden service') - - # Disable Tor hidden service subparsers.add_parser('disable-hs', help='Disable hidden service') + subparsers.add_parser('get-ports', help='Get list of Tor ports') return parser.parse_args() @@ -146,6 +143,42 @@ def get_hidden_service(): return hs_hostname + ' ' + ','.join(hs_ports) +def subcommand_get_ports(_): + """Return a list of running Tor ports.""" + try: + print('orport', _get_orport()) + except Exception: + pass + + with open(TOR_STATE_FILE, 'r') as state_file: + for line in state_file: + matches = re.match(r'^\s*TransportProxy\s+(\S*)\s+\S+:(\d+)\s*$', + line) + if matches: + print('{0} {1}'.format(matches.group(1), matches.group(2))) + + +def _get_orport(): + """Return the ORPort by querying running instance.""" + cookie = open(TOR_AUTH_COOKIE, 'rb').read() + cookie = codecs.encode(cookie, 'hex').decode() + + commands = '''AUTHENTICATE {cookie} +GETINFO net/listeners/or +QUIT +'''.format(cookie=cookie) + + tor_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + tor_socket.connect(('localhost', 9051)) + tor_socket.send(commands.encode()) + response = tor_socket.recv(1024) + tor_socket.close() + + line = response.split(b'\r\n')[1].decode() + matches = re.match(r'.*="[^:]+:(\d+)"', line) + return matches.group(1) + + def main(): """Parse arguments and perform all duties""" arguments = parse_arguments() diff --git a/actions/tor-get-ports b/actions/tor-get-ports deleted file mode 100755 index de50f4237..000000000 --- a/actions/tor-get-ports +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -# -# This file is part of Plinth. -# -# 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 . -# - -# Action to get ports used by Tor. - -echo "ORPort" `tor-get-orport` - -transports="obfs3 scramblesuit" -for transport in $transports -do - echo $transport `grep $transport /var/lib/tor/state | awk -F'[: ]*' '{print $4}'` -done diff --git a/data/etc/plinth/modules-enabled/packages b/data/etc/plinth/modules-enabled/packages deleted file mode 100644 index 4e007642b..000000000 --- a/data/etc/plinth/modules-enabled/packages +++ /dev/null @@ -1 +0,0 @@ -plinth.modules.packages diff --git a/plinth/modules/deluge/__init__.py b/plinth/modules/deluge/__init__.py index 62ee7dfdb..92df0a566 100644 --- a/plinth/modules/deluge/__init__.py +++ b/plinth/modules/deluge/__init__.py @@ -36,7 +36,7 @@ def init(): """Initialize the Deluge module.""" menu = cfg.main_menu.get('apps:index') menu.add_urlname(_('BitTorrent (Deluge)'), 'glyphicon-magnet', - 'deluge:index', 60) + 'deluge:index', 200) global service service = service_module.Service( diff --git a/plinth/modules/dynamicdns/dynamicdns.py b/plinth/modules/dynamicdns/dynamicdns.py index 88c3b3841..49890ab14 100644 --- a/plinth/modules/dynamicdns/dynamicdns.py +++ b/plinth/modules/dynamicdns/dynamicdns.py @@ -43,7 +43,7 @@ def init(): """Initialize the dynamicdns module""" menu = cfg.main_menu.get('apps:index') menu.add_urlname('Dynamic DNS', 'glyphicon-refresh', - 'dynamicdns:index', 40) + 'dynamicdns:index', 500) @package.required(['ez-ipupdate']) diff --git a/plinth/modules/help/templates/help_about.html b/plinth/modules/help/templates/help_about.html index 7bfab1f18..f4cbc5faf 100644 --- a/plinth/modules/help/templates/help_about.html +++ b/plinth/modules/help/templates/help_about.html @@ -38,8 +38,15 @@ runs on must be cheap. The software it runs on must be easy to install and administrate by anybody. It must be easy to transition from existing services.

+

There are a number of projects working to realize a future of +distributed services; we aim to bring them all together in a +convenient package.

+ +

For more information about the FreedomBox project, see the +Debian Wiki.

+

Learn more +href="https://wiki.debian.org/FreedomBox" target="_blank">Learn more »

@@ -47,20 +54,3 @@ href="http://wiki.debian.org/FreedomBox" target="_blank">Learn more

{% endblock %} - -{% block sidebar %} - - - -{% endblock %} diff --git a/plinth/modules/ikiwiki/__init__.py b/plinth/modules/ikiwiki/__init__.py index d5efd79f4..7ec839590 100644 --- a/plinth/modules/ikiwiki/__init__.py +++ b/plinth/modules/ikiwiki/__init__.py @@ -36,7 +36,7 @@ def init(): """Initialize the ikiwiki module.""" menu = cfg.main_menu.get('apps:index') menu.add_urlname(_('Wiki & Blog (Ikiwiki)'), 'glyphicon-edit', - 'ikiwiki:index', 38) + 'ikiwiki:index', 1100) global service service = service_module.Service( diff --git a/plinth/modules/mumble/__init__.py b/plinth/modules/mumble/__init__.py index a6c4343c1..07b36981e 100644 --- a/plinth/modules/mumble/__init__.py +++ b/plinth/modules/mumble/__init__.py @@ -36,7 +36,7 @@ def init(): """Intialize the Mumble module.""" menu = cfg.main_menu.get('apps:index') menu.add_urlname(_('Voice Chat (Mumble)'), 'glyphicon-headphones', - 'mumble:index', 50) + 'mumble:index', 900) global service service = service_module.Service( diff --git a/plinth/modules/owncloud/owncloud.py b/plinth/modules/owncloud/owncloud.py index d62770616..668f16233 100644 --- a/plinth/modules/owncloud/owncloud.py +++ b/plinth/modules/owncloud/owncloud.py @@ -15,6 +15,10 @@ # along with this program. If not, see . # +""" +Plinth module for configuring ownCloud. +""" + from django import forms from django.contrib import messages from django.template.response import TemplateResponse @@ -37,7 +41,8 @@ class OwnCloudForm(forms.Form): # pylint: disable-msg=W0232 def init(): """Initialize the ownCloud module""" menu = cfg.main_menu.get('apps:index') - menu.add_urlname('ownCloud', 'glyphicon-picture', 'owncloud:index', 35) + menu.add_urlname(_('File Hosting (ownCloud)'), 'glyphicon-picture', + 'owncloud:index', 700) status = get_status() diff --git a/plinth/modules/owncloud/templates/owncloud.html b/plinth/modules/owncloud/templates/owncloud.html index b5242d5ed..2a6836f2d 100644 --- a/plinth/modules/owncloud/templates/owncloud.html +++ b/plinth/modules/owncloud/templates/owncloud.html @@ -22,37 +22,27 @@ {% block content %} +

File Hosting (ownCloud)

+ +

ownCloud gives you universal access to your files through a web + interface or WebDAV. It also provides a platform to easily view & + sync your contacts, calendars and bookmarks across all your devices + and enables basic editing right on the web. Installation has minimal + server requirements, doesn't need special permissions and is + quick. ownCloud is extendable via a simple but powerful API for + applications and plugins.

+ +

When enabled, the ownCloud installation will be available + from /owncloud path on the web server. + Visit this URL to set up the initial administration account for + ownCloud.

+
{% csrf_token %} -

ownCloud

- -

When enabled, the ownCloud installation will be available - from /owncloud path on the web server. - Visit this URL to set up the initial administration account for - ownCloud.

- {{ form|bootstrap }}
{% endblock %} - -{% block sidebar %} - - - -{% endblock %} diff --git a/plinth/modules/packages/__init__.py b/plinth/modules/packages/__init__.py deleted file mode 100644 index 64b060a1a..000000000 --- a/plinth/modules/packages/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -# -# This file is part of Plinth. -# -# 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 . -# - -""" -Plinth module to manage packages -""" - -from . import packages -from .packages import init - -__all__ = ['packages', 'init'] - -depends = ['plinth.modules.system'] diff --git a/plinth/modules/packages/packages.py b/plinth/modules/packages/packages.py deleted file mode 100644 index ce92dff64..000000000 --- a/plinth/modules/packages/packages.py +++ /dev/null @@ -1,130 +0,0 @@ -# -# This file is part of Plinth. -# -# 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 . -# - -from django import forms -from django.contrib import messages -from django.template.response import TemplateResponse -from gettext import gettext as _ -import os - -from plinth import actions -from plinth import cfg - - -def get_modules_available(): - """Return list of all modules""" - output = actions.run('module-manager', ['list-available']) - return output.split() - - -def get_modules_enabled(): - """Return list of all modules""" - root = os.path.join(os.path.dirname(__file__), '..', '..') - output = actions.run('module-manager', - ['list-enabled', root]) - return output.split() - - -class PackagesForm(forms.Form): - """Packages form""" - def __init__(self, *args, **kwargs): - # pylint: disable-msg=E1002, E1101 - super(forms.Form, self).__init__(*args, **kwargs) - - modules_available = get_modules_available() - - for module in modules_available: - label = _('Enable {module}').format(module=module) - self.fields[module + '_enabled'] = forms.BooleanField( - label=label, required=False) - - -def init(): - """Initialize the Packages module""" - menu = cfg.main_menu.get('system:index') - menu.add_urlname('Package Manager', 'glyphicon-gift', 'packages:index', 20) - - -def index(request): - """Serve the form""" - status = get_status() - - form = None - - if request.method == 'POST': - form = PackagesForm(request.POST, prefix='packages') - # pylint: disable-msg=E1101 - if form.is_valid(): - _apply_changes(request, status, form.cleaned_data) - status = get_status() - form = PackagesForm(initial=status, prefix='packages') - else: - form = PackagesForm(initial=status, prefix='packages') - - return TemplateResponse(request, 'packages.html', - {'title': _('Add/Remove Plugins'), - 'form': form}) - - -def get_status(): - """Return the current status""" - modules_available = get_modules_available() - modules_enabled = get_modules_enabled() - - return {module + '_enabled': module in modules_enabled - for module in modules_available} - - -def _apply_changes(request, old_status, new_status): - """Apply form changes""" - root = os.path.join(os.path.dirname(__file__), '..', '..') - for field, enabled in new_status.items(): - if not field.endswith('_enabled'): - continue - - if old_status[field] == new_status[field]: - continue - - module = field.split('_enabled')[0] - if enabled: - try: - actions.superuser_run('module-manager', - ['enable', root, module]) - except Exception: - # TODO: need to get plinth to load the module we just - # enabled - messages.error( - request, _('Error enabling module - {module}').format( - module=module)) - else: - messages.success( - request, _('Module enabled - {module}').format( - module=module)) - else: - try: - actions.superuser_run('module-manager', - ['disable', root, module]) - except Exception: - # TODO: need a smoother way for plinth to unload the - # module - messages.error( - request, _('Error disabling module - {module}').format( - module=module)) - else: - messages.success( - request, _('Module disabled - {module}').format( - module=module)) diff --git a/plinth/modules/packages/templates/packages.html b/plinth/modules/packages/templates/packages.html deleted file mode 100644 index 6254df28d..000000000 --- a/plinth/modules/packages/templates/packages.html +++ /dev/null @@ -1,63 +0,0 @@ -{% extends "base.html" %} -{% comment %} -# -# This file is part of Plinth. -# -# 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 . -# -{% endcomment %} - -{% load bootstrap %} - -{% block content %} - -

{{ title }}

- -

aptitude purge modules

- -

aptitude install modules

- -

The modules should depend on the appropriate Debian packages.

- -

Manage Plugins

- -
- {% csrf_token %} - - {{ form|bootstrap }} - -

Enabling a plugin will cause a corresponding page to appear in - Plinth.

- - - -
- -{% endblock %} - -{% block sidebar %} - - - -{% endblock %} diff --git a/plinth/modules/packages/tests/__init__.py b/plinth/modules/packages/tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/plinth/modules/packages/urls.py b/plinth/modules/packages/urls.py deleted file mode 100644 index 6eaf99b04..000000000 --- a/plinth/modules/packages/urls.py +++ /dev/null @@ -1,28 +0,0 @@ -# -# This file is part of Plinth. -# -# 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 . -# - -""" -URLs for the Packages module -""" - -from django.conf.urls import patterns, url - - -urlpatterns = patterns( # pylint: disable-msg=C0103 - 'plinth.modules.packages.packages', - url(r'^sys/packages/$', 'index', name='index') -) diff --git a/plinth/modules/pagekite/__init__.py b/plinth/modules/pagekite/__init__.py index 18fcccbcb..a8d125462 100644 --- a/plinth/modules/pagekite/__init__.py +++ b/plinth/modules/pagekite/__init__.py @@ -31,4 +31,4 @@ def init(): """Intialize the PageKite module""" menu = cfg.main_menu.get('apps:index') menu.add_urlname(_('Public Visibility (PageKite)'), - 'glyphicon-flag', 'pagekite:index', 50) + 'glyphicon-flag', 'pagekite:index', 800) diff --git a/plinth/modules/privoxy/__init__.py b/plinth/modules/privoxy/__init__.py index fdb8d8eb4..473175166 100644 --- a/plinth/modules/privoxy/__init__.py +++ b/plinth/modules/privoxy/__init__.py @@ -36,7 +36,7 @@ def init(): """Intialize the module.""" menu = cfg.main_menu.get('apps:index') menu.add_urlname(_('Web Proxy (Privoxy)'), 'glyphicon-cloud-upload', - 'privoxy:index', 50) + 'privoxy:index', 1000) global service service = service_module.Service( diff --git a/plinth/modules/roundcube/__init__.py b/plinth/modules/roundcube/__init__.py index 56077af59..5c1ef8cf0 100644 --- a/plinth/modules/roundcube/__init__.py +++ b/plinth/modules/roundcube/__init__.py @@ -34,7 +34,7 @@ def init(): """Intialize the module.""" menu = cfg.main_menu.get('apps:index') menu.add_urlname(_('Email Client (Roundcube)'), 'glyphicon-envelope', - 'roundcube:index', 50) + 'roundcube:index', 600) def is_enabled(): """Return whether the module is enabled.""" diff --git a/plinth/modules/tor/templates/tor.html b/plinth/modules/tor/templates/tor.html index 2860c9516..2ad5a5c16 100644 --- a/plinth/modules/tor/templates/tor.html +++ b/plinth/modules/tor/templates/tor.html @@ -22,35 +22,54 @@ {% block content %} -

Tor

+

Anonymity Network (Tor)

+ +

Tor is an anonymous communication system. You can learn more about +it from the Tor Project +website. For best protection when web surfing, the Tor Project +recommends that you use +the +Tor Browser.

Status

-{% if is_running %} +{% if status.is_running %}

Tor is running {% else %}
Tor is not running {% endif %}

-

Hidden Service

+{% if status.hs_enabled %} +
+
+ + + + + + + + + + + + + +
Hidden ServicePort
{{ status.hs_hostname }}{{ status.hs_ports }}
+
+
+{% endif %} -

A hidden service will allow your {{ cfg.box_name }} to provide selected -services (such as OwnCloud or Chat) without revealing its location. -Here is the current configuration:

+

Configuration

-
    -
  • Hostname: {{ tor_hs_hostname }}
  • -
  • Ports: {{ tor_hs_ports }}
  • -
- -
+ {% csrf_token %} {{ form|bootstrap }} - +

Bridge

@@ -62,13 +81,21 @@ port-forwarded, if necessary:

- - {% for name, port in tor_ports.items %} +
+ + + + + + + + {% for name, port in status.ports.items %} - {% endfor %} + {% endfor %} +
ServicePort
{{ name }} {{ port }}
@@ -79,20 +106,3 @@ port-forwarded, if necessary:

9050.

{% endblock %} - -{% block sidebar %} - - - -{% endblock %} diff --git a/plinth/modules/tor/tor.py b/plinth/modules/tor/tor.py index 5f6eba542..d87099bc1 100644 --- a/plinth/modules/tor/tor.py +++ b/plinth/modules/tor/tor.py @@ -32,15 +32,22 @@ from plinth import package class TorForm(forms.Form): # pylint: disable=W0232 """Tor configuration form""" - hs_enabled = forms.BooleanField( - label=_('Enable Hidden Service'), + enabled = forms.BooleanField( + label=_('Enable Tor'), required=False) + hs_enabled = forms.BooleanField( + label=_('Enable Tor Hidden Service'), + required=False, + help_text=_('A hidden service will allow FreedomBox to provide ' + 'selected services (such as ownCloud or Chat) without ' + 'revealing its location.')) def init(): - """Initialize the Tor module""" + """Initialize the Tor module.""" menu = cfg.main_menu.get('apps:index') - menu.add_urlname('Tor', 'glyphicon-eye-close', 'tor:index', 30) + menu.add_urlname(_('Anonymity Network (Tor)'), 'glyphicon-eye-close', + 'tor:index', 100) @package.required(['tor']) @@ -62,17 +69,13 @@ def index(request): return TemplateResponse(request, 'tor.html', {'title': _('Tor Control Panel'), - 'is_running': status['is_running'], - 'tor_ports': status['ports'], - 'tor_hs_enabled': status['hs_enabled'], - 'tor_hs_hostname': status['hs_hostname'], - 'tor_hs_ports': status['hs_ports'], + 'status': status, 'form': form}) def get_status(): """Return the current status""" - output = actions.superuser_run('tor-get-ports') + output = actions.superuser_run('tor', ['get-ports']) port_info = output.split('\n') ports = {} for line in port_info: @@ -98,7 +101,8 @@ def get_status(): hs_hostname = hs_info[0] hs_ports = hs_info[1] - return {'is_running': action_utils.service_is_running('tor'), + return {'enabled': action_utils.service_is_enabled('tor'), + 'is_running': action_utils.service_is_running('tor'), 'ports': ports, 'hs_enabled': hs_enabled, 'hs_hostname': hs_hostname, @@ -106,16 +110,24 @@ def get_status(): def _apply_changes(request, old_status, new_status): - """Apply the changes""" - if old_status['hs_enabled'] == new_status['hs_enabled']: + """Apply the changes.""" + if old_status['enabled'] == new_status['enabled'] and \ + old_status['hs_enabled'] == new_status['hs_enabled']: messages.info(request, _('Setting unchanged')) return - if new_status['hs_enabled']: - messages.success(request, _('Tor hidden service enabled')) - command = 'enable-hs' - else: - messages.success(request, _('Tor hidden service disabled')) - command = 'disable-hs' + if old_status['enabled'] != new_status['enabled']: + if new_status['enabled']: + messages.success(request, _('Tor enabled')) + actions.superuser_run('tor', ['enable']) + else: + messages.success(request, _('Tor disabled')) + actions.superuser_run('tor', ['disable']) - actions.superuser_run('tor', [command]) + if old_status['hs_enabled'] != new_status['hs_enabled']: + if new_status['hs_enabled']: + messages.success(request, _('Tor hidden service enabled')) + actions.superuser_run('tor', ['enable-hs']) + else: + messages.success(request, _('Tor hidden service disabled')) + actions.superuser_run('tor', ['disable-hs']) diff --git a/plinth/modules/transmission/__init__.py b/plinth/modules/transmission/__init__.py index 7a1b46916..5aeb3959a 100644 --- a/plinth/modules/transmission/__init__.py +++ b/plinth/modules/transmission/__init__.py @@ -36,7 +36,7 @@ def init(): """Intialize the Transmission module.""" menu = cfg.main_menu.get('apps:index') menu.add_urlname(_('BitTorrent (Transmission)'), 'glyphicon-save', - 'transmission:index', 100) + 'transmission:index', 300) global service service = service_module.Service( diff --git a/plinth/modules/xmpp/__init__.py b/plinth/modules/xmpp/__init__.py index 7415e0071..4ce2e2988 100644 --- a/plinth/modules/xmpp/__init__.py +++ b/plinth/modules/xmpp/__init__.py @@ -38,7 +38,7 @@ def init(): """Initialize the XMPP module""" menu = cfg.main_menu.get('apps:index') menu.add_urlname(_('Chat Server (XMPP)'), 'glyphicon-comment', - 'xmpp:index', 40) + 'xmpp:index', 400) global service service = service_module.Service(