mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-13 10:30:16 +00:00
Merge remote-tracking branch 'sunil/polish'
This commit is contained in:
commit
565703270e
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
|
|
||||||
# Usage:
|
|
||||||
# module-manager list-available
|
|
||||||
# module-manager list-enabled <python_root>
|
|
||||||
# module-manager enable <python_root> <module_name>
|
|
||||||
# module-manager disable <python_root> <module_name>
|
|
||||||
|
|
||||||
# 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-<module>"
|
|
||||||
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-<module>"
|
|
||||||
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
|
|
||||||
@ -25,7 +25,6 @@ import argparse
|
|||||||
import augeas
|
import augeas
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from plinth import action_utils
|
from plinth import action_utils
|
||||||
from plinth.modules.pagekite import utils
|
from plinth.modules.pagekite import utils
|
||||||
|
|||||||
51
actions/tor
51
actions/tor
@ -22,11 +22,16 @@ Configuration helper for the Tor service
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import codecs
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
|
|
||||||
from plinth import action_utils
|
from plinth import action_utils
|
||||||
|
|
||||||
TOR_CONFIG = '/etc/tor/torrc'
|
TOR_CONFIG = '/etc/tor/torrc'
|
||||||
|
TOR_STATE_FILE = '/var/lib/tor/state'
|
||||||
|
TOR_AUTH_COOKIE = '/var/run/tor/control.authcookie'
|
||||||
|
|
||||||
|
|
||||||
def parse_arguments():
|
def parse_arguments():
|
||||||
@ -34,20 +39,12 @@ def parse_arguments():
|
|||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
|
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
|
||||||
|
|
||||||
# Enable and start the service
|
|
||||||
subparsers.add_parser('enable', help='Enable and start Tor 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')
|
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')
|
subparsers.add_parser('get-hs', help='Get hidden service')
|
||||||
|
|
||||||
# Enable Tor hidden service
|
|
||||||
subparsers.add_parser('enable-hs', help='Enable 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('disable-hs', help='Disable hidden service')
|
||||||
|
subparsers.add_parser('get-ports', help='Get list of Tor ports')
|
||||||
|
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
@ -146,6 +143,42 @@ def get_hidden_service():
|
|||||||
return hs_hostname + ' ' + ','.join(hs_ports)
|
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():
|
def main():
|
||||||
"""Parse arguments and perform all duties"""
|
"""Parse arguments and perform all duties"""
|
||||||
arguments = parse_arguments()
|
arguments = parse_arguments()
|
||||||
|
|||||||
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
|
|
||||||
# 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
|
|
||||||
@ -1 +0,0 @@
|
|||||||
plinth.modules.packages
|
|
||||||
@ -36,7 +36,7 @@ def init():
|
|||||||
"""Initialize the Deluge module."""
|
"""Initialize the Deluge module."""
|
||||||
menu = cfg.main_menu.get('apps:index')
|
menu = cfg.main_menu.get('apps:index')
|
||||||
menu.add_urlname(_('BitTorrent (Deluge)'), 'glyphicon-magnet',
|
menu.add_urlname(_('BitTorrent (Deluge)'), 'glyphicon-magnet',
|
||||||
'deluge:index', 60)
|
'deluge:index', 200)
|
||||||
|
|
||||||
global service
|
global service
|
||||||
service = service_module.Service(
|
service = service_module.Service(
|
||||||
|
|||||||
@ -43,7 +43,7 @@ def init():
|
|||||||
"""Initialize the dynamicdns module"""
|
"""Initialize the dynamicdns module"""
|
||||||
menu = cfg.main_menu.get('apps:index')
|
menu = cfg.main_menu.get('apps:index')
|
||||||
menu.add_urlname('Dynamic DNS', 'glyphicon-refresh',
|
menu.add_urlname('Dynamic DNS', 'glyphicon-refresh',
|
||||||
'dynamicdns:index', 40)
|
'dynamicdns:index', 500)
|
||||||
|
|
||||||
|
|
||||||
@package.required(['ez-ipupdate'])
|
@package.required(['ez-ipupdate'])
|
||||||
|
|||||||
@ -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
|
install and administrate by anybody. It must be easy to
|
||||||
transition from existing services.</p>
|
transition from existing services.</p>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
<p>For more information about the FreedomBox project, see the
|
||||||
|
<a href="https://wiki.debian.org/FreedomBox">Debian Wiki</a>.</p>
|
||||||
|
|
||||||
<p><a class="btn btn-primary btn-lg"
|
<p><a class="btn btn-primary btn-lg"
|
||||||
href="http://wiki.debian.org/FreedomBox" target="_blank">Learn more
|
href="https://wiki.debian.org/FreedomBox" target="_blank">Learn more
|
||||||
»</a></p>
|
»</a></p>
|
||||||
|
|
||||||
<p style='margin-top:30px'>
|
<p style='margin-top:30px'>
|
||||||
@ -47,20 +54,3 @@ href="http://wiki.debian.org/FreedomBox" target="_blank">Learn more
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block sidebar %}
|
|
||||||
|
|
||||||
<div class="sidebar">
|
|
||||||
|
|
||||||
<h3>Our Goal</h3>
|
|
||||||
|
|
||||||
<p>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.</p>
|
|
||||||
|
|
||||||
<p>For more information about the FreedomBox project, see the
|
|
||||||
<a href="http://wiki.debian.org/FreedomBox">Debian Wiki</a>.</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|||||||
@ -36,7 +36,7 @@ def init():
|
|||||||
"""Initialize the ikiwiki module."""
|
"""Initialize the ikiwiki module."""
|
||||||
menu = cfg.main_menu.get('apps:index')
|
menu = cfg.main_menu.get('apps:index')
|
||||||
menu.add_urlname(_('Wiki & Blog (Ikiwiki)'), 'glyphicon-edit',
|
menu.add_urlname(_('Wiki & Blog (Ikiwiki)'), 'glyphicon-edit',
|
||||||
'ikiwiki:index', 38)
|
'ikiwiki:index', 1100)
|
||||||
|
|
||||||
global service
|
global service
|
||||||
service = service_module.Service(
|
service = service_module.Service(
|
||||||
|
|||||||
@ -36,7 +36,7 @@ def init():
|
|||||||
"""Intialize the Mumble module."""
|
"""Intialize the Mumble module."""
|
||||||
menu = cfg.main_menu.get('apps:index')
|
menu = cfg.main_menu.get('apps:index')
|
||||||
menu.add_urlname(_('Voice Chat (Mumble)'), 'glyphicon-headphones',
|
menu.add_urlname(_('Voice Chat (Mumble)'), 'glyphicon-headphones',
|
||||||
'mumble:index', 50)
|
'mumble:index', 900)
|
||||||
|
|
||||||
global service
|
global service
|
||||||
service = service_module.Service(
|
service = service_module.Service(
|
||||||
|
|||||||
@ -15,6 +15,10 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Plinth module for configuring ownCloud.
|
||||||
|
"""
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
@ -37,7 +41,8 @@ class OwnCloudForm(forms.Form): # pylint: disable-msg=W0232
|
|||||||
def init():
|
def init():
|
||||||
"""Initialize the ownCloud module"""
|
"""Initialize the ownCloud module"""
|
||||||
menu = cfg.main_menu.get('apps:index')
|
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()
|
status = get_status()
|
||||||
|
|
||||||
|
|||||||
@ -22,37 +22,27 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<form class="form" method="post">
|
<h2>File Hosting (ownCloud)</h2>
|
||||||
{% csrf_token %}
|
|
||||||
|
|
||||||
<h2>ownCloud</h2>
|
<p>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.</p>
|
||||||
|
|
||||||
<p>When enabled, the ownCloud installation will be available
|
<p>When enabled, the ownCloud installation will be available
|
||||||
from <a href="/owncloud">/owncloud</a> path on the web server.
|
from <a href="/owncloud">/owncloud</a> path on the web server.
|
||||||
Visit this URL to set up the initial administration account for
|
Visit this URL to set up the initial administration account for
|
||||||
ownCloud.</p>
|
ownCloud.</p>
|
||||||
|
|
||||||
|
<form class="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
{{ form|bootstrap }}
|
{{ form|bootstrap }}
|
||||||
<input type="submit" class="btn btn-primary btn-md" value="Apply changes"/>
|
<input type="submit" class="btn btn-primary btn-md" value="Apply changes"/>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block sidebar %}
|
|
||||||
|
|
||||||
<div class="sidebar">
|
|
||||||
|
|
||||||
<h3>ownCloud</h3>
|
|
||||||
|
|
||||||
<p>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.</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|||||||
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
|
|
||||||
"""
|
|
||||||
Plinth module to manage packages
|
|
||||||
"""
|
|
||||||
|
|
||||||
from . import packages
|
|
||||||
from .packages import init
|
|
||||||
|
|
||||||
__all__ = ['packages', 'init']
|
|
||||||
|
|
||||||
depends = ['plinth.modules.system']
|
|
||||||
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
|
|
||||||
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))
|
|
||||||
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
{% endcomment %}
|
|
||||||
|
|
||||||
{% load bootstrap %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<h2>{{ title }}</h2>
|
|
||||||
|
|
||||||
<p><code>aptitude purge modules</code></p>
|
|
||||||
|
|
||||||
<p><code>aptitude install modules</code></p>
|
|
||||||
|
|
||||||
<p>The modules should depend on the appropriate Debian packages.</p>
|
|
||||||
|
|
||||||
<h2>Manage Plugins</h2>
|
|
||||||
|
|
||||||
<form class="form" method="post">
|
|
||||||
{% csrf_token %}
|
|
||||||
|
|
||||||
{{ form|bootstrap }}
|
|
||||||
|
|
||||||
<p>Enabling a plugin will cause a corresponding page to appear in
|
|
||||||
Plinth.</p>
|
|
||||||
|
|
||||||
<input type="submit" class="btn btn-primary" value="Update setup"/>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block sidebar %}
|
|
||||||
|
|
||||||
<div class="sidebar">
|
|
||||||
|
|
||||||
<h3>Help</h3>
|
|
||||||
|
|
||||||
<p>On this page, you can add or remove {{ cfg.product_name }}
|
|
||||||
plugins to your {{ cfg.box_name }}.</p>
|
|
||||||
|
|
||||||
<p>Plugins are just Debian packages, so Debian's usual package
|
|
||||||
management features should make this job fairly easy.</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
|
|
||||||
"""
|
|
||||||
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')
|
|
||||||
)
|
|
||||||
@ -31,4 +31,4 @@ def init():
|
|||||||
"""Intialize the PageKite module"""
|
"""Intialize the PageKite module"""
|
||||||
menu = cfg.main_menu.get('apps:index')
|
menu = cfg.main_menu.get('apps:index')
|
||||||
menu.add_urlname(_('Public Visibility (PageKite)'),
|
menu.add_urlname(_('Public Visibility (PageKite)'),
|
||||||
'glyphicon-flag', 'pagekite:index', 50)
|
'glyphicon-flag', 'pagekite:index', 800)
|
||||||
|
|||||||
@ -36,7 +36,7 @@ def init():
|
|||||||
"""Intialize the module."""
|
"""Intialize the module."""
|
||||||
menu = cfg.main_menu.get('apps:index')
|
menu = cfg.main_menu.get('apps:index')
|
||||||
menu.add_urlname(_('Web Proxy (Privoxy)'), 'glyphicon-cloud-upload',
|
menu.add_urlname(_('Web Proxy (Privoxy)'), 'glyphicon-cloud-upload',
|
||||||
'privoxy:index', 50)
|
'privoxy:index', 1000)
|
||||||
|
|
||||||
global service
|
global service
|
||||||
service = service_module.Service(
|
service = service_module.Service(
|
||||||
|
|||||||
@ -34,7 +34,7 @@ def init():
|
|||||||
"""Intialize the module."""
|
"""Intialize the module."""
|
||||||
menu = cfg.main_menu.get('apps:index')
|
menu = cfg.main_menu.get('apps:index')
|
||||||
menu.add_urlname(_('Email Client (Roundcube)'), 'glyphicon-envelope',
|
menu.add_urlname(_('Email Client (Roundcube)'), 'glyphicon-envelope',
|
||||||
'roundcube:index', 50)
|
'roundcube:index', 600)
|
||||||
|
|
||||||
def is_enabled():
|
def is_enabled():
|
||||||
"""Return whether the module is enabled."""
|
"""Return whether the module is enabled."""
|
||||||
|
|||||||
@ -22,35 +22,54 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h2>Tor</h2>
|
<h2>Anonymity Network (Tor)</h2>
|
||||||
|
|
||||||
|
<p>Tor is an anonymous communication system. You can learn more about
|
||||||
|
it from the <a href="https://www.torproject.org/">Tor Project</a>
|
||||||
|
website. For best protection when web surfing, the Tor Project
|
||||||
|
recommends that you use
|
||||||
|
the <a href="https://www.torproject.org/download/download-easy.html.en">
|
||||||
|
Tor Browser</a>.</p>
|
||||||
|
|
||||||
<h3>Status</h3>
|
<h3>Status</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
{% if is_running %}
|
{% if status.is_running %}
|
||||||
<div class='running-status active'></div> Tor is running
|
<div class='running-status active'></div> Tor is running
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class='running-status inactive'></div> Tor is not running
|
<div class='running-status inactive'></div> Tor is not running
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>Hidden Service</h3>
|
{% if status.hs_enabled %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<table class="table table-bordered table-condensed table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Hidden Service</th>
|
||||||
|
<th>Port</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{{ status.hs_hostname }}</td>
|
||||||
|
<td>{{ status.hs_ports }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<p>A hidden service will allow your {{ cfg.box_name }} to provide selected
|
<h3>Configuration</h3>
|
||||||
services (such as OwnCloud or Chat) without revealing its location.
|
|
||||||
Here is the current configuration:</p>
|
|
||||||
|
|
||||||
<ul>
|
<form class="form" method="post">
|
||||||
<li>Hostname: {{ tor_hs_hostname }}</li>
|
|
||||||
<li>Ports: {{ tor_hs_ports }}</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<form class="form form-inline" method="post">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
{{ form|bootstrap }}
|
{{ form|bootstrap }}
|
||||||
|
|
||||||
<input type="submit" class="btn btn-primary btn-sm" value="Update setup"/>
|
<input type="submit" class="btn btn-primary btn-md" value="Update setup"/>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<h3>Bridge</h3>
|
<h3>Bridge</h3>
|
||||||
@ -62,13 +81,21 @@ port-forwarded, if necessary:</p>
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
<table class="table table-bordered table-condensed">
|
<table class="table table-bordered table-condensed table-striped">
|
||||||
{% for name, port in tor_ports.items %}
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Service</th>
|
||||||
|
<th>Port</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for name, port in status.ports.items %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ name }}</td>
|
<td>{{ name }}</td>
|
||||||
<td>{{ port }}</td>
|
<td>{{ port }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -79,20 +106,3 @@ port-forwarded, if necessary:</p>
|
|||||||
9050.</p>
|
9050.</p>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block sidebar %}
|
|
||||||
|
|
||||||
<div class="sidebar">
|
|
||||||
|
|
||||||
<h3>Tor</h3>
|
|
||||||
|
|
||||||
<p>Tor is an anonymous communication system. You can learn more about
|
|
||||||
it from the <a href="https://www.torproject.org/">Tor Project</a>
|
|
||||||
website. For best protection when web surfing, the Tor Project
|
|
||||||
recommends that you use the
|
|
||||||
<a href="https://www.torproject.org/download/download-easy.html.en">
|
|
||||||
Tor Browser</a>.</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|||||||
@ -32,15 +32,22 @@ from plinth import package
|
|||||||
|
|
||||||
class TorForm(forms.Form): # pylint: disable=W0232
|
class TorForm(forms.Form): # pylint: disable=W0232
|
||||||
"""Tor configuration form"""
|
"""Tor configuration form"""
|
||||||
hs_enabled = forms.BooleanField(
|
enabled = forms.BooleanField(
|
||||||
label=_('Enable Hidden Service'),
|
label=_('Enable Tor'),
|
||||||
required=False)
|
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():
|
def init():
|
||||||
"""Initialize the Tor module"""
|
"""Initialize the Tor module."""
|
||||||
menu = cfg.main_menu.get('apps:index')
|
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'])
|
@package.required(['tor'])
|
||||||
@ -62,17 +69,13 @@ def index(request):
|
|||||||
|
|
||||||
return TemplateResponse(request, 'tor.html',
|
return TemplateResponse(request, 'tor.html',
|
||||||
{'title': _('Tor Control Panel'),
|
{'title': _('Tor Control Panel'),
|
||||||
'is_running': status['is_running'],
|
'status': status,
|
||||||
'tor_ports': status['ports'],
|
|
||||||
'tor_hs_enabled': status['hs_enabled'],
|
|
||||||
'tor_hs_hostname': status['hs_hostname'],
|
|
||||||
'tor_hs_ports': status['hs_ports'],
|
|
||||||
'form': form})
|
'form': form})
|
||||||
|
|
||||||
|
|
||||||
def get_status():
|
def get_status():
|
||||||
"""Return the current status"""
|
"""Return the current status"""
|
||||||
output = actions.superuser_run('tor-get-ports')
|
output = actions.superuser_run('tor', ['get-ports'])
|
||||||
port_info = output.split('\n')
|
port_info = output.split('\n')
|
||||||
ports = {}
|
ports = {}
|
||||||
for line in port_info:
|
for line in port_info:
|
||||||
@ -98,7 +101,8 @@ def get_status():
|
|||||||
hs_hostname = hs_info[0]
|
hs_hostname = hs_info[0]
|
||||||
hs_ports = hs_info[1]
|
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,
|
'ports': ports,
|
||||||
'hs_enabled': hs_enabled,
|
'hs_enabled': hs_enabled,
|
||||||
'hs_hostname': hs_hostname,
|
'hs_hostname': hs_hostname,
|
||||||
@ -106,16 +110,24 @@ def get_status():
|
|||||||
|
|
||||||
|
|
||||||
def _apply_changes(request, old_status, new_status):
|
def _apply_changes(request, old_status, new_status):
|
||||||
"""Apply the changes"""
|
"""Apply the changes."""
|
||||||
if old_status['hs_enabled'] == new_status['hs_enabled']:
|
if old_status['enabled'] == new_status['enabled'] and \
|
||||||
|
old_status['hs_enabled'] == new_status['hs_enabled']:
|
||||||
messages.info(request, _('Setting unchanged'))
|
messages.info(request, _('Setting unchanged'))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
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'])
|
||||||
|
|
||||||
|
if old_status['hs_enabled'] != new_status['hs_enabled']:
|
||||||
if new_status['hs_enabled']:
|
if new_status['hs_enabled']:
|
||||||
messages.success(request, _('Tor hidden service enabled'))
|
messages.success(request, _('Tor hidden service enabled'))
|
||||||
command = 'enable-hs'
|
actions.superuser_run('tor', ['enable-hs'])
|
||||||
else:
|
else:
|
||||||
messages.success(request, _('Tor hidden service disabled'))
|
messages.success(request, _('Tor hidden service disabled'))
|
||||||
command = 'disable-hs'
|
actions.superuser_run('tor', ['disable-hs'])
|
||||||
|
|
||||||
actions.superuser_run('tor', [command])
|
|
||||||
|
|||||||
@ -36,7 +36,7 @@ def init():
|
|||||||
"""Intialize the Transmission module."""
|
"""Intialize the Transmission module."""
|
||||||
menu = cfg.main_menu.get('apps:index')
|
menu = cfg.main_menu.get('apps:index')
|
||||||
menu.add_urlname(_('BitTorrent (Transmission)'), 'glyphicon-save',
|
menu.add_urlname(_('BitTorrent (Transmission)'), 'glyphicon-save',
|
||||||
'transmission:index', 100)
|
'transmission:index', 300)
|
||||||
|
|
||||||
global service
|
global service
|
||||||
service = service_module.Service(
|
service = service_module.Service(
|
||||||
|
|||||||
@ -38,7 +38,7 @@ def init():
|
|||||||
"""Initialize the XMPP module"""
|
"""Initialize the XMPP module"""
|
||||||
menu = cfg.main_menu.get('apps:index')
|
menu = cfg.main_menu.get('apps:index')
|
||||||
menu.add_urlname(_('Chat Server (XMPP)'), 'glyphicon-comment',
|
menu.add_urlname(_('Chat Server (XMPP)'), 'glyphicon-comment',
|
||||||
'xmpp:index', 40)
|
'xmpp:index', 400)
|
||||||
|
|
||||||
global service
|
global service
|
||||||
service = service_module.Service(
|
service = service_module.Service(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user