mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-07-22 11:59:33 +00:00
Services: Explicitly use ServiceForm and ServiceView
- adapted all modules to not use views.ConfigurationView anymore - removed templates that are not needed anymore - no more implicit 'enabled' and 'get_status' functions in __init__.py files - (more coherent/explicit use of Django functionality)
This commit is contained in:
parent
a9528c56d9
commit
f419c28596
@ -31,8 +31,9 @@ import socket
|
||||
import time
|
||||
|
||||
from plinth import action_utils
|
||||
from plinth.modules.tor import is_enabled, is_running, get_augeas, \
|
||||
get_real_apt_uri_path, iter_apt_uris, APT_TOR_PREFIX
|
||||
from plinth.modules.tor import is_enabled, is_running, APT_TOR_PREFIX
|
||||
from plinth.modules.tor.utils import get_real_apt_uri_path, iter_apt_uris, \
|
||||
get_augeas
|
||||
|
||||
SERVICE_FILE = '/etc/firewalld/services/tor-{0}.xml'
|
||||
TOR_CONFIG = '/files/etc/tor/torrc'
|
||||
|
||||
@ -23,8 +23,16 @@ from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
# TODO: remove this form once owncloud is removed (it's the last using it).
|
||||
class ConfigurationForm(forms.Form):
|
||||
"""Generic configuration form for simple modules."""
|
||||
enabled = forms.BooleanField(
|
||||
label=_('Enable application'),
|
||||
required=False)
|
||||
|
||||
|
||||
class ServiceForm(forms.Form):
|
||||
"""Generic configuration form for a service."""
|
||||
is_enabled = forms.BooleanField(
|
||||
label=_('Enable application'),
|
||||
required=False)
|
||||
|
||||
@ -24,6 +24,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from plinth import cfg
|
||||
from plinth import service as service_module
|
||||
from plinth.utils import format_lazy
|
||||
from plinth.views import ServiceView
|
||||
|
||||
# pylint: disable=C0103
|
||||
|
||||
@ -66,15 +67,6 @@ def setup(helper, old_version=False):
|
||||
helper.install(['avahi-daemon'])
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current settings from server."""
|
||||
return {'enabled': service.is_enabled(),
|
||||
'is_running': service.is_running()}
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
if should_enable:
|
||||
service.enable()
|
||||
else:
|
||||
service.disable()
|
||||
class AvahiServiceView(ServiceView):
|
||||
service_id = managed_services[0]
|
||||
description = description
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<h3>{% trans "Status" %}</h3>
|
||||
|
||||
<p class="running-status-parent">
|
||||
{% if status.is_running %}
|
||||
<span class="running-status active"></span>
|
||||
{% trans "Service discovery server is running" %}
|
||||
{% else %}
|
||||
<span class="running-status inactive"></span>
|
||||
{% trans "Service discovery server is not running" %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -21,10 +21,10 @@ URLs for the service discovery module.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.modules.avahi import AvahiServiceView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^sys/avahi/$', ConfigurationView.as_view(module_name='avahi'),
|
||||
url(r'^sys/avahi/$', AvahiServiceView.as_view(),
|
||||
name='index'),
|
||||
]
|
||||
|
||||
@ -60,27 +60,6 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current settings from server."""
|
||||
return {'enabled': service.is_enabled(),
|
||||
'is_running': service.is_running(),
|
||||
'time_zone': get_current_time_zone()}
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
if should_enable:
|
||||
service.enable()
|
||||
else:
|
||||
service.disable()
|
||||
|
||||
|
||||
def get_current_time_zone():
|
||||
"""Get current time zone."""
|
||||
time_zone = open('/etc/timezone').read().rstrip()
|
||||
return time_zone or 'none'
|
||||
|
||||
|
||||
def diagnose():
|
||||
"""Run diagnostics and return the results."""
|
||||
results = []
|
||||
|
||||
@ -24,13 +24,11 @@ from django.utils.translation import ugettext_lazy as _
|
||||
import glob
|
||||
import re
|
||||
|
||||
from plinth.forms import ServiceForm
|
||||
|
||||
class DateTimeForm(forms.Form):
|
||||
|
||||
class DateTimeForm(ServiceForm):
|
||||
"""Date/time configuration form."""
|
||||
enabled = forms.BooleanField(
|
||||
label=_('Enable network time'),
|
||||
required=False)
|
||||
|
||||
time_zone = forms.ChoiceField(
|
||||
label=_('Time Zone'),
|
||||
help_text=_('Set your time zone to get accurate timestamps. \
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "app.html" %}
|
||||
{% extends "service.html" %}
|
||||
{% comment %}
|
||||
#
|
||||
# This file is part of Plinth.
|
||||
@ -18,33 +18,8 @@
|
||||
#
|
||||
{% endcomment %}
|
||||
|
||||
{% load bootstrap %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<h3>{% trans "Status" %}</h3>
|
||||
|
||||
<p class="running-status-parent">
|
||||
{% if status.is_running %}
|
||||
<span class="running-status active"></span>
|
||||
{% trans "Network time server is running" %}
|
||||
{% else %}
|
||||
<span class="running-status inactive"></span>
|
||||
{% trans "Network time server is not running" %}
|
||||
{% endif %}
|
||||
{% block diagnostics %}
|
||||
<p>
|
||||
{% include "diagnostics_button.html" with module="datetime" %}
|
||||
</p>
|
||||
{% include "diagnostics_button.html" with module="datetime" %}
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@ -21,10 +21,9 @@ URLs for the date and time module
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from .views import DateTimeServiceView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^sys/datetime/$', ConfigurationView.as_view(module_name='datetime'),
|
||||
name='index'),
|
||||
url(r'^sys/datetime/$', DateTimeServiceView.as_view(), name='index'),
|
||||
]
|
||||
|
||||
@ -25,31 +25,34 @@ import logging
|
||||
|
||||
from .forms import DateTimeForm
|
||||
from plinth import actions
|
||||
from plinth import views
|
||||
from plinth.modules import datetime
|
||||
from plinth.views import ServiceView
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ConfigurationView(views.ConfigurationView):
|
||||
"""Serve configuration page."""
|
||||
class DateTimeServiceView(ServiceView):
|
||||
description = datetime.description
|
||||
form_class = DateTimeForm
|
||||
service_id = datetime.managed_services[0]
|
||||
template_name = "datetime.html"
|
||||
|
||||
def apply_changes(self, old_status, new_status):
|
||||
"""Apply the changes."""
|
||||
modified = False
|
||||
def get_initial(self):
|
||||
return {'is_enabled': self.service.is_enabled(),
|
||||
'is_running': self.service.is_running(),
|
||||
'time_zone': self.get_current_time_zone()}
|
||||
|
||||
if old_status['enabled'] != new_status['enabled']:
|
||||
if new_status['enabled']:
|
||||
datetime.service.enable()
|
||||
else:
|
||||
datetime.service.disable()
|
||||
modified = True
|
||||
messages.success(self.request, _('Configuration updated'))
|
||||
def get_current_time_zone(self):
|
||||
"""Get current time zone."""
|
||||
time_zone = open('/etc/timezone').read().rstrip()
|
||||
return time_zone or 'none'
|
||||
|
||||
def form_valid(self, form):
|
||||
old_status = form.initial
|
||||
new_status = form.cleaned_data
|
||||
|
||||
if old_status['time_zone'] != new_status['time_zone'] and \
|
||||
new_status['time_zone'] != 'none':
|
||||
modified = True
|
||||
try:
|
||||
actions.superuser_run(
|
||||
'timezone-change', [new_status['time_zone']])
|
||||
@ -60,4 +63,4 @@ class ConfigurationView(views.ConfigurationView):
|
||||
else:
|
||||
messages.success(self.request, _('Time zone set'))
|
||||
|
||||
return modified
|
||||
return super().form_valid(form)
|
||||
|
||||
@ -20,7 +20,6 @@ Plinth module to configure a Deluge web client.
|
||||
"""
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from functools import partial
|
||||
|
||||
from plinth import actions
|
||||
from plinth import action_utils
|
||||
@ -32,6 +31,10 @@ version = 1
|
||||
|
||||
depends = ['apps']
|
||||
|
||||
service = None
|
||||
|
||||
managed_services = ['deluge-web']
|
||||
|
||||
title = _('BitTorrent Web Client (Deluge)')
|
||||
|
||||
description = [
|
||||
@ -43,10 +46,6 @@ description = [
|
||||
'it immediately after enabling this service.')
|
||||
]
|
||||
|
||||
service = None
|
||||
|
||||
managed_services = ['deluge-web']
|
||||
|
||||
|
||||
def init():
|
||||
"""Initialize the Deluge module."""
|
||||
@ -56,7 +55,7 @@ def init():
|
||||
global service
|
||||
service = service_module.Service(
|
||||
managed_services[0], title, ports=['http', 'https'], is_external=True,
|
||||
is_enabled=is_enabled, enable=_enable, disable=_disable)
|
||||
is_enabled=is_enabled, enable=enable, disable=disable)
|
||||
|
||||
|
||||
def setup(helper, old_version=None):
|
||||
@ -66,23 +65,20 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current settings."""
|
||||
return {'enabled': service.is_enabled(),
|
||||
'is_running': service.is_running()}
|
||||
|
||||
|
||||
def is_enabled():
|
||||
"""Return whether the module is enabled."""
|
||||
return (action_utils.webserver_is_enabled('deluge-plinth') and
|
||||
action_utils.service_is_enabled('deluge-web'))
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
sub_command = 'enable' if should_enable else 'disable'
|
||||
actions.superuser_run('deluge', [sub_command])
|
||||
service.notify_enabled(None, should_enable)
|
||||
def enable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('deluge', ['enable'])
|
||||
|
||||
|
||||
def disable():
|
||||
"""Disable the module."""
|
||||
actions.superuser_run('deluge', ['disable'])
|
||||
|
||||
|
||||
def diagnose():
|
||||
@ -95,7 +91,3 @@ def diagnose():
|
||||
'https://{host}/deluge', extra_options=['--no-check-certificate']))
|
||||
|
||||
return results
|
||||
|
||||
|
||||
_enable = partial(enable, True)
|
||||
_disable = partial(enable, False)
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<h3>{% trans "Status" %}</h3>
|
||||
|
||||
<p class="running-status-parent">
|
||||
{% if status.is_running %}
|
||||
<span class="running-status active"></span>
|
||||
{% trans "deluge-web is running" %}
|
||||
{% else %}
|
||||
<span class="running-status inactive"></span>
|
||||
{% trans "deluge-web is not running" %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% include "diagnostics_button.html" with module="deluge" %}
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -21,10 +21,14 @@ URLs for the Deluge module.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.modules import deluge
|
||||
from plinth.views import ServiceView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/deluge/$', ConfigurationView.as_view(module_name='deluge'),
|
||||
name='index'),
|
||||
url(r'^apps/deluge/$', ServiceView.as_view(
|
||||
description=deluge.description,
|
||||
diagnostics_module_name="deluge",
|
||||
service_id=deluge.managed_services[0]
|
||||
), name='index'),
|
||||
]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "app.html" %}
|
||||
{% extends "base.html" %}
|
||||
{% comment %}
|
||||
#
|
||||
# This file is part of Plinth.
|
||||
@ -20,7 +20,33 @@
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
{% block content %}
|
||||
<h2>{{ title }}</h2>
|
||||
|
||||
{% for paragraph in description %}
|
||||
<p>{{ paragraph|safe }}</p>
|
||||
{% endfor %}
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
If your Internet provider changes your IP address periodically
|
||||
(i.e. every 24h), it may be hard for others to find you on the
|
||||
Internet. This will prevent others from finding services which are
|
||||
provided by this {box_name}.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
The solution is to assign a DNS name to your IP address and
|
||||
update the DNS name every time your IP is changed by your
|
||||
Internet provider. Dynamic DNS allows you to push your current
|
||||
public IP address to a
|
||||
<a href='http://gnudip2.sourceforge.net/' target='_blank'>
|
||||
GnuDIP</a> server. Afterwards, the server will assign your DNS name
|
||||
to the new IP, and if someone from the Internet asks for your DNS
|
||||
name, they will get a response with your current IP address.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
If you are looking for a free dynamic DNS account, you may find
|
||||
@ -39,4 +65,5 @@
|
||||
and TCP port 443 (HTTPS).
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@ -20,7 +20,6 @@ Plinth module to configure ikiwiki
|
||||
"""
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from functools import partial
|
||||
|
||||
from plinth import actions
|
||||
from plinth import action_utils
|
||||
@ -32,6 +31,8 @@ version = 1
|
||||
|
||||
depends = ['apps']
|
||||
|
||||
service = None
|
||||
|
||||
title = _('Wiki and Blog (ikiwiki)')
|
||||
|
||||
description = [
|
||||
@ -39,8 +40,6 @@ description = [
|
||||
'from <a href="/ikiwiki">/ikiwiki</a>.')
|
||||
]
|
||||
|
||||
service = None
|
||||
|
||||
|
||||
def init():
|
||||
"""Initialize the ikiwiki module."""
|
||||
@ -50,7 +49,7 @@ def init():
|
||||
global service
|
||||
service = service_module.Service(
|
||||
'ikiwiki', title, ports=['http', 'https'], is_external=True,
|
||||
is_enabled=is_enabled, enable=_enable, disable=_disable)
|
||||
is_enabled=is_enabled, enable=enable, disable=disable)
|
||||
|
||||
|
||||
def setup(helper, old_version=None):
|
||||
@ -66,21 +65,19 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current setting."""
|
||||
return {'enabled': is_enabled()}
|
||||
|
||||
|
||||
def is_enabled():
|
||||
"""Return whether the module is enabled."""
|
||||
return action_utils.webserver_is_enabled('ikiwiki-plinth')
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
sub_command = 'enable' if should_enable else 'disable'
|
||||
actions.superuser_run('ikiwiki', [sub_command])
|
||||
service.notify_enabled(None, should_enable)
|
||||
def enable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('ikiwiki', ['enable'])
|
||||
|
||||
|
||||
def disable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('ikiwiki', ['disable'])
|
||||
|
||||
|
||||
def diagnose():
|
||||
@ -91,7 +88,3 @@ def diagnose():
|
||||
'https://{host}/ikiwiki', extra_options=['--no-check-certificate']))
|
||||
|
||||
return results
|
||||
|
||||
|
||||
_enable = partial(enable, True)
|
||||
_disable = partial(enable, False)
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
{% include "diagnostics_button.html" with module="ikiwiki" %}
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -26,7 +26,7 @@ from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/ikiwiki/$',
|
||||
views.ConfigurationView.as_view(module_name='ikiwiki'), name='index'),
|
||||
views.IkiwikiServiceView.as_view(), name='index'),
|
||||
url(r'^apps/ikiwiki/manage/$', views.manage, name='manage'),
|
||||
url(r'^apps/ikiwiki/(?P<name>[\w.@+-]+)/delete/$', views.delete,
|
||||
name='delete'),
|
||||
|
||||
@ -25,9 +25,11 @@ from django.shortcuts import redirect
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
from .forms import IkiwikiCreateForm
|
||||
from plinth import actions
|
||||
from plinth import views
|
||||
from plinth.modules import ikiwiki
|
||||
|
||||
from .forms import IkiwikiCreateForm
|
||||
|
||||
|
||||
subsubmenu = [{'url': reverse_lazy('ikiwiki:index'),
|
||||
@ -38,14 +40,18 @@ subsubmenu = [{'url': reverse_lazy('ikiwiki:index'),
|
||||
'text': ugettext_lazy('Create')}]
|
||||
|
||||
|
||||
class ConfigurationView(views.ConfigurationView):
|
||||
class IkiwikiServiceView(views.ServiceView):
|
||||
"""Serve configuration page."""
|
||||
service_id = "ikiwiki"
|
||||
template_name = "apache_service.html"
|
||||
diagnostics_module_name = "ikiwiki"
|
||||
description = ikiwiki.description
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Return the context data for rendering the template view."""
|
||||
if 'subsubmenu' not in kwargs:
|
||||
kwargs['subsubmenu'] = subsubmenu
|
||||
|
||||
return super().get_context_data(**kwargs)
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['subsubmenu'] = subsubmenu
|
||||
return context
|
||||
|
||||
|
||||
def manage(request):
|
||||
|
||||
@ -25,12 +25,17 @@ from plinth import action_utils
|
||||
from plinth import cfg
|
||||
from plinth import service as service_module
|
||||
from plinth.utils import format_lazy
|
||||
from plinth.views import ServiceView
|
||||
|
||||
|
||||
version = 1
|
||||
|
||||
depends = ['apps']
|
||||
|
||||
service = None
|
||||
|
||||
managed_services = ['minetest-server']
|
||||
|
||||
title = _('Block Sandbox (Minetest)')
|
||||
|
||||
description = [
|
||||
@ -42,11 +47,6 @@ description = [
|
||||
'is needed.'), box_name=_(cfg.box_name)),
|
||||
]
|
||||
|
||||
service = None
|
||||
|
||||
managed_services = ['minetest-server']
|
||||
|
||||
|
||||
def init():
|
||||
"""Initialize the module."""
|
||||
menu = cfg.main_menu.get('apps:index')
|
||||
@ -63,18 +63,11 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current service status."""
|
||||
return {'enabled': service.is_enabled(),
|
||||
'is_running': service.is_running()}
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
if should_enable:
|
||||
service.enable()
|
||||
else:
|
||||
service.disable()
|
||||
class MinetestServiceView(ServiceView):
|
||||
service_id = managed_services[0]
|
||||
template_name = "apache_service.html"
|
||||
diagnostics_module_name = "minetest"
|
||||
description = description
|
||||
|
||||
|
||||
def diagnose():
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<h3>{% trans "Status" %}</h3>
|
||||
|
||||
<p class="running-status-parent">
|
||||
{% if status.is_running %}
|
||||
<span class="running-status active"></span>
|
||||
{% trans "Minetest server is running" %}
|
||||
{% else %}
|
||||
<span class="running-status inactive"></span>
|
||||
{% trans "Minetest server is not running" %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% include "diagnostics_button.html" with module="minetest" %}
|
||||
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -21,10 +21,9 @@ URLs for the minetest module.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.modules.minetest import MinetestServiceView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/minetest/$', ConfigurationView.as_view(module_name='minetest'),
|
||||
name='index'),
|
||||
url(r'^apps/minetest/$', MinetestServiceView.as_view(), name='index'),
|
||||
]
|
||||
|
||||
@ -24,6 +24,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from plinth import action_utils
|
||||
from plinth import cfg
|
||||
from plinth import service as service_module
|
||||
from plinth.views import ServiceView
|
||||
|
||||
|
||||
version = 1
|
||||
@ -32,6 +33,10 @@ depends = ['apps']
|
||||
|
||||
title = _('Voice Chat (Mumble)')
|
||||
|
||||
service = None
|
||||
|
||||
managed_services = ['mumble-server']
|
||||
|
||||
description = [
|
||||
_('Mumble is an open source, low-latency, encrypted, high quality '
|
||||
'voice chat software.'),
|
||||
@ -41,10 +46,6 @@ description = [
|
||||
'from your desktop and Android devices are available.')
|
||||
]
|
||||
|
||||
service = None
|
||||
|
||||
managed_services = ['mumble-server']
|
||||
|
||||
|
||||
def init():
|
||||
"""Intialize the Mumble module."""
|
||||
@ -56,26 +57,18 @@ def init():
|
||||
managed_services[0], title, is_external=True)
|
||||
|
||||
|
||||
class MumbleServiceView(ServiceView):
|
||||
service_id = managed_services[0]
|
||||
diagnostics_module_name = "mumble"
|
||||
description = description
|
||||
|
||||
|
||||
def setup(helper, old_version=None):
|
||||
"""Install and configure the module."""
|
||||
helper.install(['mumble-server'])
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current settings from server."""
|
||||
return {'enabled': service.is_enabled(),
|
||||
'is_running': service.is_running()}
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
if should_enable:
|
||||
service.enable()
|
||||
else:
|
||||
service.disable()
|
||||
|
||||
|
||||
def diagnose():
|
||||
"""Run diagnostics and return the results."""
|
||||
results = []
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<h3>{% trans "Status" %}</h3>
|
||||
|
||||
<p class="running-status-parent">
|
||||
{% if status.is_running %}
|
||||
<span class="running-status active"></span>
|
||||
{% trans "Mumble server is running" %}
|
||||
{% else %}
|
||||
<span class="running-status inactive"></span>
|
||||
{% trans "Mumble server is not running" %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% include "diagnostics_button.html" with module="mumble" %}
|
||||
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -21,10 +21,9 @@ URLs for the Mumble module
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.modules.mumble import MumbleServiceView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/mumble/$', ConfigurationView.as_view(module_name='mumble'),
|
||||
name='index'),
|
||||
url(r'^apps/mumble/$', MumbleServiceView.as_view(), name='index'),
|
||||
]
|
||||
|
||||
@ -32,6 +32,10 @@ version = 1
|
||||
|
||||
depends = ['apps']
|
||||
|
||||
service = None
|
||||
|
||||
managed_services = ['openvpn@freedombox']
|
||||
|
||||
title = _('Virtual Private Network (OpenVPN)')
|
||||
|
||||
description = [
|
||||
@ -45,10 +49,6 @@ description = [
|
||||
'for added security and anonymity.'), box_name=_(cfg.box_name))
|
||||
]
|
||||
|
||||
service = None
|
||||
|
||||
managed_services = ['openvpn@freedombox']
|
||||
|
||||
|
||||
def init():
|
||||
"""Intialize the OpenVPN module."""
|
||||
|
||||
@ -21,7 +21,6 @@ Plinth module to configure PageKite
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from plinth import cfg
|
||||
from plinth.utils import format_lazy
|
||||
|
||||
from . import utils
|
||||
|
||||
@ -31,39 +30,6 @@ depends = ['apps', 'names']
|
||||
|
||||
title = _('Public Visibility (PageKite)')
|
||||
|
||||
description = [
|
||||
format_lazy(
|
||||
_('PageKite is a system for exposing {box_name} services when '
|
||||
'you don\'t have a direct connection to the Internet. You only '
|
||||
'need this if your {box_name} services are unreachable from '
|
||||
'the rest of the Internet. This includes the following '
|
||||
'situations:'), box_name=_(cfg.box_name)),
|
||||
|
||||
format_lazy(
|
||||
_('{box_name} is behind a restricted firewall.'),
|
||||
box_name=_(cfg.box_name)),
|
||||
|
||||
format_lazy(
|
||||
_('{box_name} is connected to a (wireless) router which you '
|
||||
'don\'t control.'), box_name=_(cfg.box_name)),
|
||||
|
||||
_('Your ISP does not provide you an external IP address and '
|
||||
'instead provides Internet connection through NAT.'),
|
||||
|
||||
_('Your ISP does not provide you a static IP address and your IP '
|
||||
'address changes evertime you connect to Internet.'),
|
||||
|
||||
_('Your ISP limits incoming connections.'),
|
||||
|
||||
format_lazy(
|
||||
_('PageKite works around NAT, firewalls and IP-address limitations '
|
||||
'by using a combination of tunnels and reverse proxies. You can '
|
||||
'use any pagekite service provider, for example '
|
||||
'<a href="https://pagekite.net">pagekite.net</a>. In future it '
|
||||
'might be possible to use your buddy\'s {box_name} for this.'),
|
||||
box_name=_(cfg.box_name))
|
||||
]
|
||||
|
||||
|
||||
def init():
|
||||
"""Intialize the PageKite module"""
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "app.html" %}
|
||||
{% extends "base.html" %}
|
||||
{% comment %}
|
||||
#
|
||||
# This file is part of Plinth.
|
||||
@ -20,7 +20,54 @@
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
{% block content %}
|
||||
<h2>{{ title }}</h2>
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
PageKite is a system for exposing {box_name} services when
|
||||
you don\'t have a direct connection to the Internet. You only
|
||||
need this if your {{ box_name }} services are unreachable from
|
||||
the rest of the Internet. This includes the following
|
||||
situations:
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
{{ box_name }} {% trans "is behind a restricted firewall." %}
|
||||
</li>
|
||||
<li>
|
||||
{{ box_name }}
|
||||
{% blocktrans trimmed %}
|
||||
is connected to a (wireless) router which you don't control.
|
||||
{% endblocktrans %}
|
||||
</li>
|
||||
<li>
|
||||
{% blocktrans trimmed %}
|
||||
Your ISP does not provide you an external IP address and
|
||||
instead provides Internet connection through NAT.
|
||||
{% endblocktrans %}
|
||||
</li>
|
||||
<li>
|
||||
{% blocktrans trimmed %}
|
||||
Your ISP does not provide you a static IP address and your IP
|
||||
address changes evertime you connect to Internet.
|
||||
{% endblocktrans %}
|
||||
</li>
|
||||
<li>
|
||||
Your ISP limits incoming connections.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
PageKite works around NAT, firewalls and IP-address limitations
|
||||
by using a combination of tunnels and reverse proxies. You can
|
||||
use any pagekite service provider, for example
|
||||
<a href="https://pagekite.net">pagekite.net</a>. In future it
|
||||
might be possible to use your buddy's {{ box_name }} for this.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a class="btn btn-primary btn-md" href="{% url 'pagekite:configure' %}">
|
||||
|
||||
@ -42,7 +42,6 @@ def index(request):
|
||||
"""Serve introduction page"""
|
||||
return TemplateResponse(request, 'pagekite_introduction.html',
|
||||
{'title': pagekite.title,
|
||||
'description': pagekite.description,
|
||||
'subsubmenu': subsubmenu})
|
||||
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@ from plinth import action_utils
|
||||
from plinth import cfg
|
||||
from plinth import service as service_module
|
||||
from plinth.utils import format_lazy
|
||||
from plinth.views import ServiceView
|
||||
|
||||
|
||||
version = 1
|
||||
@ -73,18 +74,10 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current settings from server."""
|
||||
return {'enabled': service.is_enabled(),
|
||||
'is_running': service.is_running()}
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
if should_enable:
|
||||
service.enable()
|
||||
else:
|
||||
service.disable()
|
||||
class PrivoxyServiceView(ServiceView):
|
||||
service_id = managed_services[0]
|
||||
diagnostics_module_name = 'privoxy'
|
||||
description = description
|
||||
|
||||
|
||||
def diagnose():
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<h3>{% trans "Status" %}</h3>
|
||||
|
||||
<p class="running-status-parent">
|
||||
{% if status.is_running %}
|
||||
<span class="running-status active"></span>
|
||||
{% trans "Privoxy is running" %}
|
||||
{% else %}
|
||||
<span class="running-status inactive"></span>
|
||||
{% trans "Privoxy is not running" %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% include "diagnostics_button.html" with module="privoxy" %}
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -21,10 +21,9 @@ URLs for the Privoxy module.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.modules.privoxy import PrivoxyServiceView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/privoxy/$', ConfigurationView.as_view(module_name='privoxy'),
|
||||
name='index'),
|
||||
url(r'^apps/privoxy/$', PrivoxyServiceView.as_view(), name='index'),
|
||||
]
|
||||
|
||||
@ -25,11 +25,16 @@ from plinth import action_utils
|
||||
from plinth import cfg
|
||||
from plinth import service as service_module
|
||||
from plinth.utils import format_lazy
|
||||
from plinth.views import ServiceView
|
||||
|
||||
version = 1
|
||||
|
||||
depends = ['apps']
|
||||
|
||||
service = None
|
||||
|
||||
managed_services = ['quasselcore']
|
||||
|
||||
title = _('IRC Client (Quassel)')
|
||||
|
||||
description = [
|
||||
@ -49,10 +54,6 @@ description = [
|
||||
'are available.')
|
||||
]
|
||||
|
||||
service = None
|
||||
|
||||
managed_services = ['quasselcore']
|
||||
|
||||
|
||||
def init():
|
||||
"""Initialize the quassel module."""
|
||||
@ -61,7 +62,13 @@ def init():
|
||||
|
||||
global service
|
||||
service = service_module.Service(
|
||||
managed_services[0], title, description=description, is_external=True)
|
||||
managed_services[0], title, is_external=True)
|
||||
|
||||
|
||||
class QuasselServiceView(ServiceView):
|
||||
service_id = managed_services[0]
|
||||
diagnostics_module_name = "quassel"
|
||||
description = description
|
||||
|
||||
|
||||
def setup(helper, old_version=None):
|
||||
@ -70,20 +77,6 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current service status."""
|
||||
return {'enabled': service.is_enabled(),
|
||||
'is_running': service.is_running()}
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
if should_enable:
|
||||
service.enable()
|
||||
else:
|
||||
service.disable()
|
||||
|
||||
|
||||
def diagnose():
|
||||
"""Run diagnostics and return the results."""
|
||||
results = []
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<h3>{% trans "Status" %}</h3>
|
||||
|
||||
<p class="running-status-parent">
|
||||
{% if status.is_running %}
|
||||
<span class="running-status active"></span>
|
||||
{% trans "Quassel core service is running" %}
|
||||
{% else %}
|
||||
<span class="running-status inactive"></span>
|
||||
{% trans "Quassel core service is not running" %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% include "diagnostics_button.html" with module="quassel" %}
|
||||
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -21,10 +21,9 @@ URLs for the quassel module.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.modules.quassel import QuasselServiceView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/quassel/$', ConfigurationView.as_view(module_name='quassel'),
|
||||
name='index'),
|
||||
url(r'^apps/quassel/$', QuasselServiceView.as_view(), name='index'),
|
||||
]
|
||||
|
||||
@ -19,8 +19,6 @@
|
||||
Plinth module for radicale.
|
||||
"""
|
||||
|
||||
from functools import partial
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from plinth import actions
|
||||
@ -28,12 +26,17 @@ from plinth import action_utils
|
||||
from plinth import cfg
|
||||
from plinth import service as service_module
|
||||
from plinth.utils import format_lazy
|
||||
from plinth.views import ServiceView
|
||||
|
||||
|
||||
version = 1
|
||||
|
||||
depends = ['apps']
|
||||
|
||||
service = None
|
||||
|
||||
managed_services = ['radicale']
|
||||
|
||||
title = _('Calendar and Addressbook (Radicale)')
|
||||
|
||||
description = [
|
||||
@ -46,10 +49,6 @@ description = [
|
||||
'login.'), box_name=_(cfg.box_name)),
|
||||
]
|
||||
|
||||
service = None
|
||||
|
||||
managed_services = ['radicale']
|
||||
|
||||
|
||||
def init():
|
||||
"""Initialize the radicale module."""
|
||||
@ -59,7 +58,13 @@ def init():
|
||||
global service
|
||||
service = service_module.Service(
|
||||
managed_services[0], title, ports=['http', 'https'], is_external=True,
|
||||
enable=_enable, disable=_disable)
|
||||
enable=enable, disable=disable)
|
||||
|
||||
|
||||
class RadicaleServiceView(ServiceView):
|
||||
service_id = managed_services[0]
|
||||
diagnostics_module_name = 'radicale'
|
||||
description = description
|
||||
|
||||
|
||||
def setup(helper, old_version=None):
|
||||
@ -69,17 +74,14 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current service status."""
|
||||
return {'enabled': service.is_enabled(),
|
||||
'is_running': service.is_running()}
|
||||
def enable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('radicale', ['enable'])
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
sub_command = 'enable' if should_enable else 'disable'
|
||||
actions.superuser_run('radicale', [sub_command])
|
||||
service.notify_enabled(None, should_enable)
|
||||
def disable():
|
||||
"""Disable the module."""
|
||||
actions.superuser_run('radicale', ['disable'])
|
||||
|
||||
|
||||
def diagnose():
|
||||
@ -92,7 +94,3 @@ def diagnose():
|
||||
'https://{host}/radicale', extra_options=['--no-check-certificate']))
|
||||
|
||||
return results
|
||||
|
||||
|
||||
_enable = partial(enable, True)
|
||||
_disable = partial(enable, False)
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<h3>{% trans "Status" %}</h3>
|
||||
|
||||
<p class="running-status-parent">
|
||||
{% if status.is_running %}
|
||||
<span class="running-status active"></span>
|
||||
{% trans "Radicale service is running" %}
|
||||
{% else %}
|
||||
<span class="running-status inactive"></span>
|
||||
{% trans "Radicale service is not running" %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% include "diagnostics_button.html" with module="radicale" %}
|
||||
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -21,10 +21,9 @@ URLs for the radicale module.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.modules.radicale import RadicaleServiceView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/radicale/$', ConfigurationView.as_view(module_name='radicale'),
|
||||
name='index'),
|
||||
url(r'^apps/radicale/$', RadicaleServiceView.as_view(), name='index'),
|
||||
]
|
||||
|
||||
@ -25,6 +25,7 @@ from plinth import actions
|
||||
from plinth import action_utils
|
||||
from plinth import cfg
|
||||
from plinth import service as service_module
|
||||
from plinth.views import ServiceView
|
||||
|
||||
version = 1
|
||||
|
||||
@ -69,6 +70,12 @@ def init():
|
||||
is_external=True)
|
||||
|
||||
|
||||
class ReproServiceView(ServiceView):
|
||||
service_id = managed_services[0]
|
||||
diagnostics_module_name = "repro"
|
||||
description = description
|
||||
|
||||
|
||||
def setup(helper, old_version=None):
|
||||
"""Install and configure the module."""
|
||||
helper.install(['repro'])
|
||||
@ -76,20 +83,6 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current service status."""
|
||||
return {'enabled': service.is_enabled(),
|
||||
'is_running': service.is_running()}
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
if should_enable:
|
||||
service.enable()
|
||||
else:
|
||||
service.disable()
|
||||
|
||||
|
||||
def diagnose():
|
||||
"""Run diagnostics and return the results."""
|
||||
results = []
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<h3>{% trans "Status" %}</h3>
|
||||
|
||||
<p class="running-status-parent">
|
||||
{% if status.is_running %}
|
||||
<span class="running-status active"></span>
|
||||
{% trans "repro service is running" %}
|
||||
{% else %}
|
||||
<span class="running-status inactive"></span>
|
||||
{% trans "repro service is not running" %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% include "diagnostics_button.html" with module="repro" %}
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -21,10 +21,9 @@ URLs for the repro module.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.modules.repro import ReproServiceView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/repro/$', ConfigurationView.as_view(module_name='repro'),
|
||||
name='index'),
|
||||
url(r'^apps/repro/$', ReproServiceView.as_view(), name='index'),
|
||||
]
|
||||
|
||||
@ -57,23 +57,9 @@ def init():
|
||||
|
||||
global service
|
||||
service = service_module.Service(
|
||||
managed_services[0], title, ports=['http', 'https'], is_external=False,
|
||||
description=description)
|
||||
managed_services[0], title, ports=['http', 'https'], is_external=False)
|
||||
|
||||
|
||||
def setup(helper, old_version=None):
|
||||
"""Install and configure the module."""
|
||||
helper.install(['node-restore'])
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current settings."""
|
||||
return {'enabled': service.is_enabled()}
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
if should_enable:
|
||||
service.enable()
|
||||
else:
|
||||
service.disable()
|
||||
|
||||
@ -21,10 +21,13 @@ URLs for the reStore module.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.views import ServiceView
|
||||
from plinth.modules import restore
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/restore/$', ConfigurationView.as_view(module_name='restore'),
|
||||
name='index'),
|
||||
url(r'^apps/restore/$', ServiceView.as_view(
|
||||
service_id=restore.managed_services[0],
|
||||
description=restore.description
|
||||
), name='index'),
|
||||
]
|
||||
|
||||
@ -24,6 +24,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from plinth import actions
|
||||
from plinth import action_utils
|
||||
from plinth import cfg
|
||||
from plinth import service as service_module
|
||||
|
||||
|
||||
version = 1
|
||||
@ -54,12 +55,19 @@ description = [
|
||||
'>https://www.google.com/settings/security/lesssecureapps</a>).'),
|
||||
]
|
||||
|
||||
service = None
|
||||
|
||||
|
||||
def init():
|
||||
"""Intialize the module."""
|
||||
menu = cfg.main_menu.get('apps:index')
|
||||
menu.add_urlname(title, 'glyphicon-envelope', 'roundcube:index', 600)
|
||||
|
||||
global service
|
||||
service = service_module.Service(
|
||||
'roundcube', title, ports=['http', 'https'], is_external=True,
|
||||
is_enabled=is_enabled, enable=enable, disable=disable)
|
||||
|
||||
|
||||
def setup(helper, old_version=None):
|
||||
"""Install and configure the module."""
|
||||
@ -68,20 +76,19 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', actions.superuser_run, 'roundcube', ['setup'])
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current status."""
|
||||
return {'enabled': is_enabled()}
|
||||
|
||||
|
||||
def is_enabled():
|
||||
"""Return whether the module is enabled."""
|
||||
return action_utils.webserver_is_enabled('roundcube')
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
sub_command = 'enable' if should_enable else 'disable'
|
||||
actions.superuser_run('roundcube', [sub_command])
|
||||
def enable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('roundcube', ['enable'])
|
||||
|
||||
|
||||
def disable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('roundcube', ['disable'])
|
||||
|
||||
|
||||
def diagnose():
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
{% include "diagnostics_button.html" with module="roundcube" %}
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -21,10 +21,15 @@ URLs for the Roundcube module.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.views import ServiceView
|
||||
from plinth.modules import roundcube
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/roundcube/$',
|
||||
ConfigurationView.as_view(module_name='roundcube'), name='index'),
|
||||
url(r'^apps/roundcube/$', ServiceView.as_view(
|
||||
service_id="roundcube",
|
||||
diagnostics_module_name="roundcube",
|
||||
description=roundcube.description,
|
||||
template_name="apache_service.html"
|
||||
), name='index'),
|
||||
]
|
||||
|
||||
@ -19,8 +19,6 @@
|
||||
Plinth module to configure Shaarli.
|
||||
"""
|
||||
|
||||
from functools import partial
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from plinth import actions
|
||||
@ -55,7 +53,7 @@ def init():
|
||||
global service
|
||||
service = service_module.Service(
|
||||
'shaarli', title, ports=['http', 'https'], is_external=True,
|
||||
is_enabled=is_enabled, enable=_enable, disable=_disable)
|
||||
is_enabled=is_enabled, enable=enable, disable=disable)
|
||||
|
||||
|
||||
def setup(helper, old_version=None):
|
||||
@ -64,22 +62,17 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current settings."""
|
||||
return {'enabled': service.is_enabled()}
|
||||
|
||||
|
||||
def is_enabled():
|
||||
"""Return whether the module is enabled."""
|
||||
return action_utils.webserver_is_enabled('shaarli')
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
sub_command = 'enable' if should_enable else 'disable'
|
||||
actions.superuser_run('shaarli', [sub_command])
|
||||
service.notify_enabled(None, should_enable)
|
||||
def enable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('shaarli', ['enable'])
|
||||
|
||||
|
||||
_enable = partial(enable, True)
|
||||
_disable = partial(enable, False)
|
||||
def disable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('shaarli', ['disable'])
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -21,10 +21,14 @@ URLs for the Shaarli module.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.views import ServiceView
|
||||
from plinth.modules import shaarli
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/shaarli/$', ConfigurationView.as_view(module_name='shaarli'),
|
||||
name='index'),
|
||||
url(r'^apps/shaarli/$', ServiceView.as_view(
|
||||
service_id="shaarli",
|
||||
description=shaarli.description,
|
||||
template_name="apache_service.html"
|
||||
), name='index'),
|
||||
]
|
||||
|
||||
@ -19,10 +19,7 @@
|
||||
Plinth module to configure Tor.
|
||||
"""
|
||||
|
||||
import augeas
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import glob
|
||||
import itertools
|
||||
import json
|
||||
|
||||
from plinth import actions
|
||||
@ -32,6 +29,8 @@ from plinth import service as service_module
|
||||
from plinth.modules.names import SERVICES
|
||||
from plinth.signals import domain_added, domain_removed
|
||||
|
||||
from . import utils as tor_utils
|
||||
|
||||
|
||||
version = 1
|
||||
|
||||
@ -73,7 +72,7 @@ def init():
|
||||
is_external=True, is_enabled=is_enabled, is_running=is_running)
|
||||
|
||||
# Register hidden service name with Name Services module.
|
||||
hs_info = get_hs()
|
||||
hs_info = tor_utils.get_hs()
|
||||
hostname = hs_info['hostname']
|
||||
hs_virtports = [port['virtport'] for port in hs_info['ports']]
|
||||
|
||||
@ -108,7 +107,7 @@ def setup(helper, old_version=None):
|
||||
def update_hidden_service_domain(status=None):
|
||||
"""Update HS domain with Name Services module."""
|
||||
if not status:
|
||||
status = get_status()
|
||||
status = tor_utils.get_status()
|
||||
|
||||
domain_removed.send_robust(
|
||||
sender='tor', domain_type='hiddenservice')
|
||||
@ -131,107 +130,6 @@ def is_running():
|
||||
return action_utils.service_is_running('tor')
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Return current Tor status."""
|
||||
output = actions.superuser_run('tor', ['get-ports'])
|
||||
ports = json.loads(output)
|
||||
|
||||
hs_info = get_hs()
|
||||
hs_services = []
|
||||
hs_virtports = [port['virtport'] for port in hs_info['ports']]
|
||||
for service_type in SERVICES:
|
||||
if str(service_type[2]) in hs_virtports:
|
||||
hs_services.append(service_type[0])
|
||||
|
||||
return {'enabled': is_enabled(),
|
||||
'is_running': is_running(),
|
||||
'ports': ports,
|
||||
'hs_enabled': hs_info['enabled'],
|
||||
'hs_status': hs_info['status'],
|
||||
'hs_hostname': hs_info['hostname'],
|
||||
'hs_ports': hs_info['ports'],
|
||||
'hs_services': hs_services,
|
||||
'apt_transport_tor_enabled': is_apt_transport_tor_enabled()}
|
||||
|
||||
|
||||
def get_hs():
|
||||
"""Return hidden service status."""
|
||||
output = actions.superuser_run('tor', ['get-hs'])
|
||||
return json.loads(output)
|
||||
|
||||
|
||||
def get_augeas():
|
||||
"""Return an instance of Augeaus for processing APT configuration."""
|
||||
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||
aug.set('/augeas/load/Aptsources/lens', 'Aptsources.lns')
|
||||
aug.set('/augeas/load/Aptsources/incl[last() + 1]', '/etc/apt/sources.list')
|
||||
aug.set('/augeas/load/Aptsources/incl[last() + 1]',
|
||||
'/etc/apt/sources.list.d/*.list')
|
||||
aug.load()
|
||||
|
||||
# Currently, augeas does not handle Deb822 format, it error out.
|
||||
if aug.match('/augeas/files/etc/apt/sources.list/error') or \
|
||||
aug.match('/augeas/files/etc/apt/sources.list.d//error'):
|
||||
raise Exception('Error parsing sources list')
|
||||
|
||||
# Starting with Apt 1.1, /etc/apt/sources.list.d/*.sources will
|
||||
# contain files with Deb822 format. If they are found, error out
|
||||
# for now. XXX: Provide proper support Deb822 format with a new
|
||||
# Augeas lens.
|
||||
if glob.glob('/etc/apt/sources.list.d/*.sources'):
|
||||
raise Exception('Can not handle Deb822 source files')
|
||||
|
||||
return aug
|
||||
|
||||
|
||||
def iter_apt_uris(aug):
|
||||
"""Iterate over all the APT source URIs."""
|
||||
return itertools.chain.from_iterable([aug.match(path)
|
||||
for path in APT_SOURCES_URI_PATHS])
|
||||
|
||||
|
||||
def get_real_apt_uri_path(aug, path):
|
||||
"""Return the actual path which contains APT URL.
|
||||
|
||||
XXX: This is a workaround for Augeas bug parsing Apt source files
|
||||
with '[options]'. Remove this workaround after Augeas lens is
|
||||
fixed.
|
||||
"""
|
||||
uri = aug.get(path)
|
||||
if uri[0] == '[':
|
||||
parent_path = path.rsplit('/', maxsplit=1)[0]
|
||||
skipped = False
|
||||
for child_path in aug.match(parent_path + '/*')[1:]:
|
||||
if skipped:
|
||||
return child_path
|
||||
|
||||
value = aug.get(child_path)
|
||||
if value[-1] == ']':
|
||||
skipped = True
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def is_apt_transport_tor_enabled():
|
||||
"""Return whether APT is set to download packages over Tor."""
|
||||
try:
|
||||
aug = get_augeas()
|
||||
except Exception:
|
||||
# If there was an error with parsing or there are Deb822
|
||||
# files.
|
||||
return False
|
||||
|
||||
for uri_path in iter_apt_uris(aug):
|
||||
uri_path = get_real_apt_uri_path(aug, uri_path)
|
||||
uri = aug.get(uri_path)
|
||||
if not uri.startswith(APT_TOR_PREFIX) and \
|
||||
(uri.startswith('http://') or uri.startswith('https://')):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def diagnose():
|
||||
"""Run diagnostics and return the results."""
|
||||
results = []
|
||||
|
||||
132
plinth/modules/tor/utils.py
Normal file
132
plinth/modules/tor/utils.py
Normal file
@ -0,0 +1,132 @@
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
"""
|
||||
Tor utility functions
|
||||
"""
|
||||
|
||||
import augeas
|
||||
import glob
|
||||
import itertools
|
||||
import json
|
||||
|
||||
from plinth import actions
|
||||
from plinth.modules import tor
|
||||
from plinth.modules.names import SERVICES
|
||||
|
||||
|
||||
def get_hs():
|
||||
"""Return hidden service status."""
|
||||
output = actions.superuser_run('tor', ['get-hs'])
|
||||
return json.loads(output)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Return current Tor status."""
|
||||
output = actions.superuser_run('tor', ['get-ports'])
|
||||
ports = json.loads(output)
|
||||
|
||||
hs_info = get_hs()
|
||||
hs_services = []
|
||||
hs_virtports = [port['virtport'] for port in hs_info['ports']]
|
||||
for service_type in SERVICES:
|
||||
if str(service_type[2]) in hs_virtports:
|
||||
hs_services.append(service_type[0])
|
||||
|
||||
return {'enabled': tor.is_enabled(),
|
||||
'is_running': tor.is_running(),
|
||||
'ports': ports,
|
||||
'hs_enabled': hs_info['enabled'],
|
||||
'hs_status': hs_info['status'],
|
||||
'hs_hostname': hs_info['hostname'],
|
||||
'hs_ports': hs_info['ports'],
|
||||
'hs_services': hs_services,
|
||||
'apt_transport_tor_enabled': \
|
||||
_is_apt_transport_tor_enabled()
|
||||
}
|
||||
|
||||
|
||||
def iter_apt_uris(aug):
|
||||
"""Iterate over all the APT source URIs."""
|
||||
return itertools.chain.from_iterable([aug.match(path) for \
|
||||
path in tor.APT_SOURCES_URI_PATHS])
|
||||
|
||||
|
||||
def get_real_apt_uri_path(aug, path):
|
||||
"""Return the actual path which contains APT URL.
|
||||
|
||||
XXX: This is a workaround for Augeas bug parsing Apt source files
|
||||
with '[options]'. Remove this workaround after Augeas lens is
|
||||
fixed.
|
||||
"""
|
||||
uri = aug.get(path)
|
||||
if uri[0] == '[':
|
||||
parent_path = path.rsplit('/', maxsplit=1)[0]
|
||||
skipped = False
|
||||
for child_path in aug.match(parent_path + '/*')[1:]:
|
||||
if skipped:
|
||||
return child_path
|
||||
|
||||
value = aug.get(child_path)
|
||||
if value[-1] == ']':
|
||||
skipped = True
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def get_augeas():
|
||||
"""Return an instance of Augeaus for processing APT configuration."""
|
||||
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||
aug.set('/augeas/load/Aptsources/lens', 'Aptsources.lns')
|
||||
aug.set('/augeas/load/Aptsources/incl[last() + 1]', '/etc/apt/sources.list')
|
||||
aug.set('/augeas/load/Aptsources/incl[last() + 1]',
|
||||
'/etc/apt/sources.list.d/*.list')
|
||||
aug.load()
|
||||
|
||||
# Currently, augeas does not handle Deb822 format, it error out.
|
||||
if aug.match('/augeas/files/etc/apt/sources.list/error') or \
|
||||
aug.match('/augeas/files/etc/apt/sources.list.d//error'):
|
||||
raise Exception('Error parsing sources list')
|
||||
|
||||
# Starting with Apt 1.1, /etc/apt/sources.list.d/*.sources will
|
||||
# contain files with Deb822 format. If they are found, error out
|
||||
# for now. XXX: Provide proper support Deb822 format with a new
|
||||
# Augeas lens.
|
||||
if glob.glob('/etc/apt/sources.list.d/*.sources'):
|
||||
raise Exception('Can not handle Deb822 source files')
|
||||
|
||||
return aug
|
||||
|
||||
|
||||
def _is_apt_transport_tor_enabled():
|
||||
"""Return whether APT is set to download packages over Tor."""
|
||||
try:
|
||||
aug = get_augeas()
|
||||
except Exception:
|
||||
# If there was an error with parsing or there are Deb822
|
||||
# files.
|
||||
return False
|
||||
|
||||
for uri_path in iter_apt_uris(aug):
|
||||
uri_path = get_real_apt_uri_path(aug, uri_path)
|
||||
uri = aug.get(uri_path)
|
||||
if not uri.startswith(tor.APT_TOR_PREFIX) and \
|
||||
(uri.startswith('http://') or uri.startswith('https://')):
|
||||
return False
|
||||
|
||||
return True
|
||||
@ -18,16 +18,17 @@
|
||||
"""
|
||||
Plinth module for configuring Tor.
|
||||
"""
|
||||
|
||||
from django.contrib import messages
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from . import utils as tor_utils
|
||||
from .forms import TorForm
|
||||
from plinth import actions
|
||||
from plinth.errors import ActionError
|
||||
from plinth.modules import tor
|
||||
|
||||
|
||||
config_process = None
|
||||
|
||||
|
||||
@ -36,7 +37,7 @@ def index(request):
|
||||
if config_process:
|
||||
_collect_config_result(request)
|
||||
|
||||
status = tor.get_status()
|
||||
status = tor_utils.get_status()
|
||||
form = None
|
||||
|
||||
if request.method == 'POST':
|
||||
@ -44,7 +45,7 @@ def index(request):
|
||||
# pylint: disable=E1101
|
||||
if form.is_valid():
|
||||
_apply_changes(request, status, form.cleaned_data)
|
||||
status = tor.get_status()
|
||||
status = tor_utils.get_status()
|
||||
form = TorForm(initial=status, prefix='tor')
|
||||
else:
|
||||
form = TorForm(initial=status, prefix='tor')
|
||||
@ -109,7 +110,7 @@ def _collect_config_result(request):
|
||||
if return_code is None:
|
||||
return
|
||||
|
||||
status = tor.get_status()
|
||||
status = tor_utils.get_status()
|
||||
|
||||
tor.socks_service.notify_enabled(None, status['enabled'])
|
||||
tor.bridge_service.notify_enabled(None, status['enabled'])
|
||||
|
||||
@ -20,9 +20,7 @@ Plinth module to configure Transmission server
|
||||
"""
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from functools import partial
|
||||
import json
|
||||
import socket
|
||||
|
||||
from plinth import actions
|
||||
from plinth import action_utils
|
||||
@ -39,7 +37,8 @@ title = _('BitTorrent (Transmission)')
|
||||
description = [
|
||||
_('BitTorrent is a peer-to-peer file sharing protocol. '
|
||||
'Transmission daemon handles Bitorrent file sharing. Note that '
|
||||
'BitTorrent is not anonymous.')
|
||||
'BitTorrent is not anonymous.'),
|
||||
_('Access the web interface at <a href="/transmission">/transmission</a>.')
|
||||
]
|
||||
|
||||
service = None
|
||||
@ -57,8 +56,7 @@ def init():
|
||||
global service
|
||||
service = service_module.Service(
|
||||
managed_services[0], title, ports=['http', 'https'], is_external=True,
|
||||
is_enabled=is_enabled, enable=_enable, disable=_disable,
|
||||
description=description)
|
||||
is_enabled=is_enabled, enable=enable, disable=disable)
|
||||
|
||||
|
||||
def setup(helper, old_version=None):
|
||||
@ -74,30 +72,20 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current settings from Transmission server."""
|
||||
configuration = open(TRANSMISSION_CONFIG, 'r').read()
|
||||
status = json.loads(configuration)
|
||||
status = {key.translate(str.maketrans({'-': '_'})): value
|
||||
for key, value in status.items()}
|
||||
status['enabled'] = is_enabled()
|
||||
status['is_running'] = service.is_running()
|
||||
status['hostname'] = socket.gethostname()
|
||||
|
||||
return status
|
||||
|
||||
|
||||
def is_enabled():
|
||||
"""Return whether the module is enabled."""
|
||||
return (action_utils.service_is_enabled('transmission-daemon') and
|
||||
action_utils.webserver_is_enabled('transmission-plinth'))
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
sub_command = 'enable' if should_enable else 'disable'
|
||||
actions.superuser_run('transmission', [sub_command])
|
||||
service.notify_enabled(None, should_enable)
|
||||
def enable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('transmission', ['enable'])
|
||||
|
||||
|
||||
def disable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('transmission', ['disable'])
|
||||
|
||||
|
||||
def diagnose():
|
||||
@ -111,7 +99,3 @@ def diagnose():
|
||||
extra_options=['--no-check-certificate']))
|
||||
|
||||
return results
|
||||
|
||||
|
||||
_enable = partial(enable, True)
|
||||
_disable = partial(enable, False)
|
||||
|
||||
@ -22,10 +22,10 @@ Plinth module for configuring Transmission.
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from plinth.forms import ConfigurationForm
|
||||
from plinth.forms import ServiceForm
|
||||
|
||||
|
||||
class TransmissionForm(ConfigurationForm): # pylint: disable=W0232
|
||||
class TransmissionForm(ServiceForm): # pylint: disable=W0232
|
||||
"""Transmission configuration form"""
|
||||
download_dir = forms.CharField(
|
||||
label=_('Download directory'),
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
Access the web interface at <a href="/transmission">/transmission</a>.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
<h3>{% trans "Status" %}</h3>
|
||||
|
||||
<p class="running-status-parent">
|
||||
{% if status.is_running %}
|
||||
<span class='running-status active'></span>
|
||||
{% trans "Transmission daemon is running" %}
|
||||
{% else %}
|
||||
<span class='running-status inactive'></span>
|
||||
{% trans "Transmission daemon is not running." %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% include "diagnostics_button.html" with module="transmission" %}
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -21,11 +21,10 @@ URLs for the Transmission module.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from .views import TransmissionConfigurationView
|
||||
from .views import TransmissionServiceView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/transmission/$',
|
||||
TransmissionConfigurationView.as_view(module_name='transmission'),
|
||||
name='index'),
|
||||
TransmissionServiceView.as_view(), name='index'),
|
||||
]
|
||||
|
||||
@ -23,21 +23,39 @@ from django.contrib import messages
|
||||
from django.utils.translation import ugettext as _
|
||||
import json
|
||||
import logging
|
||||
import socket
|
||||
|
||||
from .forms import TransmissionForm
|
||||
from plinth import actions
|
||||
from plinth import views
|
||||
from plinth.modules import transmission
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TransmissionConfigurationView(views.ConfigurationView):
|
||||
class TransmissionServiceView(views.ServiceView):
|
||||
"""Serve configuration page."""
|
||||
description = transmission.description
|
||||
diagnostics_module_name = 'transmission'
|
||||
form_class = TransmissionForm
|
||||
service_id = transmission.managed_services[0]
|
||||
|
||||
def apply_changes(self, old_status, new_status):
|
||||
def get_initial(self):
|
||||
"""Get the current settings from Transmission server."""
|
||||
configuration = open(transmission.TRANSMISSION_CONFIG, 'r').read()
|
||||
status = json.loads(configuration)
|
||||
status = {key.translate(str.maketrans({'-': '_'})): value
|
||||
for key, value in status.items()}
|
||||
status['is_enabled'] = self.service.is_enabled()
|
||||
status['is_running'] = self.service.is_running()
|
||||
status['hostname'] = socket.gethostname()
|
||||
|
||||
return status
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Apply the changes submitted in the form."""
|
||||
modified = super().apply_changes(old_status, new_status)
|
||||
old_status = form.initial
|
||||
new_status = form.cleaned_data
|
||||
|
||||
if old_status['download_dir'] != new_status['download_dir'] or \
|
||||
old_status['rpc_username'] != new_status['rpc_username'] or \
|
||||
@ -51,6 +69,5 @@ class TransmissionConfigurationView(views.ConfigurationView):
|
||||
actions.superuser_run('transmission', ['merge-configuration'],
|
||||
input=json.dumps(new_configuration).encode())
|
||||
messages.success(self.request, _('Configuration updated'))
|
||||
return True
|
||||
|
||||
return modified
|
||||
return super().form_valid(form)
|
||||
|
||||
@ -20,7 +20,6 @@ Plinth module to configure Tiny Tiny RSS.
|
||||
"""
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from functools import partial
|
||||
|
||||
from plinth import actions
|
||||
from plinth import action_utils
|
||||
@ -56,7 +55,7 @@ def init():
|
||||
global service
|
||||
service = service_module.Service(
|
||||
managed_services[0], title, ports=['http', 'https'], is_external=True,
|
||||
is_enabled=is_enabled, enable=_enable, disable=_disable)
|
||||
is_enabled=is_enabled, enable=enable, disable=disable)
|
||||
|
||||
|
||||
def setup(helper, old_version=None):
|
||||
@ -67,23 +66,20 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current settings."""
|
||||
return {'enabled': is_enabled(),
|
||||
'is_running': service.is_running()}
|
||||
|
||||
|
||||
def is_enabled():
|
||||
"""Return whether the module is enabled."""
|
||||
return (action_utils.service_is_enabled('tt-rss') and
|
||||
action_utils.webserver_is_enabled('tt-rss-plinth'))
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
sub_command = 'enable' if should_enable else 'disable'
|
||||
actions.superuser_run('ttrss', [sub_command])
|
||||
service.notify_enabled(None, should_enable)
|
||||
def enable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('ttrss', ['enable'])
|
||||
|
||||
|
||||
def disable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('ttrss', ['disable'])
|
||||
|
||||
|
||||
def diagnose():
|
||||
@ -94,7 +90,3 @@ def diagnose():
|
||||
'https://{host}/tt-rss', extra_options=['--no-check-certificate']))
|
||||
|
||||
return results
|
||||
|
||||
|
||||
_enable = partial(enable, True)
|
||||
_disable = partial(enable, False)
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
{% extends "app.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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<h3>{% trans "Status" %}</h3>
|
||||
|
||||
<p class="running-status-parent">
|
||||
{% if status.is_running %}
|
||||
<span class="running-status active"></span>
|
||||
{% trans "Tiny Tiny RSS feed update service is running" %}
|
||||
{% else %}
|
||||
<span class="running-status inactive"></span>
|
||||
{% trans "Tiny Tiny RSS feed update service is not running" %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% include "diagnostics_button.html" with module="ttrss" %}
|
||||
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -21,10 +21,15 @@ URLs for the Tiny Tiny RSS module.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.views import ServiceView
|
||||
from plinth.modules import ttrss
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/ttrss/$', ConfigurationView.as_view(module_name='ttrss'),
|
||||
name='index'),
|
||||
url(r'^apps/ttrss/$', ServiceView.as_view(
|
||||
service_id=ttrss.managed_services[0],
|
||||
diagnostics_module_name="ttrss",
|
||||
description=ttrss.description,
|
||||
template_name="apache_service.html"
|
||||
), name='index'),
|
||||
]
|
||||
|
||||
@ -23,6 +23,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from plinth import actions
|
||||
from plinth import cfg
|
||||
from plinth import service as service_module
|
||||
|
||||
|
||||
version = 1
|
||||
@ -39,11 +40,17 @@ description = [
|
||||
'night. You don\'t normally need to start the upgrade process.')
|
||||
]
|
||||
|
||||
service = None
|
||||
|
||||
|
||||
def init():
|
||||
"""Initialize the module."""
|
||||
menu = cfg.main_menu.get('system:index')
|
||||
menu.add_urlname(title, 'glyphicon-refresh', 'upgrades:index', 21)
|
||||
global service
|
||||
service = service_module.Service(
|
||||
'auto-upgrades', title, is_external=False, is_enabled=is_enabled,
|
||||
enable=enable, disable=disable)
|
||||
|
||||
|
||||
def setup(helper, old_version=None):
|
||||
@ -52,18 +59,17 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', actions.superuser_run, 'upgrades', ['enable-auto'])
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Return the current status."""
|
||||
return {'auto_upgrades_enabled': 'is_enabled'}
|
||||
|
||||
|
||||
def is_enabled():
|
||||
"""Return whether the module is enabled."""
|
||||
output = actions.run('upgrades', ['check-auto'])
|
||||
return 'True' in output.split()
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
option = 'enable-auto' if should_enable else 'disable-auto'
|
||||
actions.superuser_run('upgrades', [option])
|
||||
def enable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('upgrades', ['enable-auto'])
|
||||
|
||||
|
||||
def disable():
|
||||
"""Disable the module."""
|
||||
actions.superuser_run('upgrades', ['disable-auto'])
|
||||
|
||||
@ -25,7 +25,7 @@ from . import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^sys/upgrades/$',
|
||||
views.ConfigurationView.as_view(module_name='upgrades'), name='index'),
|
||||
url(r'^sys/upgrades/$', views.UpgradesConfigurationView.as_view(),
|
||||
name='index'),
|
||||
url(r'^sys/upgrades/upgrade/$', views.upgrade, name='upgrade'),
|
||||
]
|
||||
|
||||
@ -23,11 +23,11 @@ from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.views.generic.edit import FormView
|
||||
import subprocess
|
||||
|
||||
from .forms import ConfigureForm
|
||||
from plinth import actions
|
||||
from plinth import views
|
||||
from plinth.errors import ActionError
|
||||
from plinth.modules import upgrades
|
||||
|
||||
@ -40,43 +40,52 @@ LOG_FILE = '/var/log/unattended-upgrades/unattended-upgrades.log'
|
||||
LOCK_FILE = '/var/log/dpkg/lock'
|
||||
|
||||
|
||||
class ConfigurationView(views.ConfigurationView):
|
||||
class UpgradesConfigurationView(FormView):
|
||||
"""Serve configuration page."""
|
||||
form_class = ConfigureForm
|
||||
success_url = reverse_lazy('upgrades:index')
|
||||
template_name = "upgrades_configure.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
"""Return the context data for rendering the template view."""
|
||||
if 'subsubmenu' not in kwargs:
|
||||
kwargs['subsubmenu'] = subsubmenu
|
||||
context = super().get_context_data(*args, **kwargs)
|
||||
context['subsubmenu'] = subsubmenu
|
||||
context['title'] = upgrades.title
|
||||
context['description'] = upgrades.description
|
||||
return context
|
||||
|
||||
return super().get_context_data(**kwargs)
|
||||
def get_initial(self):
|
||||
return {'auto_upgrades_enabled': upgrades.service.is_enabled()}
|
||||
|
||||
def get_template_names(self):
|
||||
"""Return the list of template names for the view."""
|
||||
return ['upgrades_configure.html']
|
||||
|
||||
def apply_changes(self, old_status, new_status):
|
||||
def form_valid(self, form):
|
||||
"""Apply the form changes."""
|
||||
old_status = form.initial
|
||||
new_status = form.cleaned_data
|
||||
|
||||
if old_status['auto_upgrades_enabled'] \
|
||||
== new_status['auto_upgrades_enabled']:
|
||||
return False
|
||||
!= new_status['auto_upgrades_enabled']:
|
||||
|
||||
try:
|
||||
upgrades.enable(new_status['auto_upgrades_enabled'])
|
||||
except ActionError as exception:
|
||||
error = exception.args[2]
|
||||
messages.error(
|
||||
self.request,
|
||||
_('Error when configuring unattended-upgrades: {error}')
|
||||
.format(error=error))
|
||||
return True
|
||||
try:
|
||||
if new_status['auto_upgrades_enabled']:
|
||||
upgrades.service.enable()
|
||||
else:
|
||||
upgrades.service.disable()
|
||||
except ActionError as exception:
|
||||
error = exception.args[2]
|
||||
messages.error(
|
||||
self.request,
|
||||
_('Error when configuring unattended-upgrades: {error}')
|
||||
.format(error=error))
|
||||
|
||||
if new_status['auto_upgrades_enabled']:
|
||||
messages.success(self.request, _('Automatic upgrades enabled'))
|
||||
if new_status['auto_upgrades_enabled']:
|
||||
messages.success(self.request, _('Automatic upgrades enabled'))
|
||||
else:
|
||||
messages.success(self.request, _('Automatic upgrades disabled'))
|
||||
else:
|
||||
messages.success(self.request, _('Automatic upgrades disabled'))
|
||||
messages.info(self.request, _('Settings unchanged'))
|
||||
|
||||
return super().form_valid(form)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def is_package_manager_busy():
|
||||
|
||||
@ -20,7 +20,6 @@ Plinth module to configure XMPP server
|
||||
"""
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from functools import partial
|
||||
import logging
|
||||
import socket
|
||||
|
||||
@ -28,6 +27,7 @@ from plinth import actions
|
||||
from plinth import action_utils
|
||||
from plinth import cfg
|
||||
from plinth import service as service_module
|
||||
from plinth.views import ServiceView
|
||||
from plinth.signals import pre_hostname_change, post_hostname_change
|
||||
from plinth.signals import domainname_change
|
||||
|
||||
@ -63,8 +63,7 @@ def init():
|
||||
global service
|
||||
service = service_module.Service(
|
||||
'ejabberd', title, ports=['xmpp-client', 'xmpp-server', 'xmpp-bosh'],
|
||||
is_external=True, is_enabled=is_enabled, enable=_enable,
|
||||
disable=_disable)
|
||||
is_external=True, is_enabled=is_enabled, enable=enable, disable=disable)
|
||||
|
||||
pre_hostname_change.connect(on_pre_hostname_change)
|
||||
post_hostname_change.connect(on_post_hostname_change)
|
||||
@ -83,11 +82,16 @@ def setup(helper, old_version=None):
|
||||
helper.call('post', service.notify_enabled, None, True)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the current settings."""
|
||||
return {'enabled': service.is_enabled(),
|
||||
'is_running': service.is_running(),
|
||||
'domainname': get_domainname()}
|
||||
class EjabberdServiceView(ServiceView):
|
||||
service_id = managed_services[0]
|
||||
template_name = "xmpp.html"
|
||||
description = description
|
||||
diagnostics_module_name = "xmpp"
|
||||
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
context = super().get_context_data(*args, **kwargs)
|
||||
context['domainname'] = get_domainname()
|
||||
return context
|
||||
|
||||
|
||||
def is_enabled():
|
||||
@ -102,11 +106,14 @@ def get_domainname():
|
||||
return '.'.join(fqdn.split('.')[1:])
|
||||
|
||||
|
||||
def enable(should_enable):
|
||||
"""Enable/disable the module."""
|
||||
sub_command = 'enable' if should_enable else 'disable'
|
||||
actions.superuser_run('xmpp', [sub_command])
|
||||
service.notify_enabled(None, should_enable)
|
||||
def enable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('xmpp', ['enable'])
|
||||
|
||||
|
||||
def disable():
|
||||
"""Enable the module."""
|
||||
actions.superuser_run('xmpp', ['disable'])
|
||||
|
||||
|
||||
def on_pre_hostname_change(sender, old_hostname, new_hostname, **kwargs):
|
||||
@ -163,7 +170,3 @@ def diagnose():
|
||||
results.extend(action_utils.diagnose_url_on_all('http://{host}/jwchat'))
|
||||
|
||||
return results
|
||||
|
||||
|
||||
_enable = partial(enable, True)
|
||||
_disable = partial(enable, False)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "app.html" %}
|
||||
{% extends "service.html" %}
|
||||
{% comment %}
|
||||
#
|
||||
# This file is part of Plinth.
|
||||
@ -18,10 +18,13 @@
|
||||
#
|
||||
{% endcomment %}
|
||||
|
||||
{% load bootstrap %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
{% block description %}
|
||||
|
||||
{% for paragraph in description %}
|
||||
<p>{{ paragraph|safe }}</p>
|
||||
{% endfor %}
|
||||
|
||||
<p>
|
||||
{% url 'config:index' as index_url %}
|
||||
@ -37,30 +40,4 @@
|
||||
<a href='/jwchat' target='_blank' class='btn btn-primary'>
|
||||
{% trans "Launch web client" %}</a>
|
||||
</p>
|
||||
|
||||
<h3>{% trans "Status" %}</h3>
|
||||
|
||||
<p class="running-status-parent">
|
||||
{% if status.is_running %}
|
||||
<span class="running-status active"></span>
|
||||
{% trans "ejabberd is running" %}
|
||||
{% else %}
|
||||
<span class="running-status inactive"></span>
|
||||
{% trans "ejabberd is not running" %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% include "diagnostics_button.html" with module="xmpp" %}
|
||||
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@ -21,10 +21,9 @@ URLs for the XMPP module
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from plinth.views import ConfigurationView
|
||||
from plinth.modules.xmpp import EjabberdServiceView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^apps/xmpp/$', ConfigurationView.as_view(module_name='xmpp'),
|
||||
name='index'),
|
||||
url(r'^apps/xmpp/$', EjabberdServiceView.as_view(), name='index'),
|
||||
]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "app.html" %}
|
||||
{% extends "service.html" %}
|
||||
{% comment %}
|
||||
#
|
||||
# This file is part of Plinth.
|
||||
@ -18,20 +18,11 @@
|
||||
#
|
||||
{% endcomment %}
|
||||
|
||||
{% load bootstrap %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block configuration %}
|
||||
|
||||
<h3>Configuration</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
{% comment %}
|
||||
# The status block uses is_running, but apache services by default don't
|
||||
# provide this method. We could use is_enabled instead, but this information is
|
||||
# available in the enable/disable checkbox already. So omit it altogether.
|
||||
{% endcomment %}
|
||||
|
||||
{% block status %}
|
||||
{% endblock %}
|
||||
67
plinth/templates/service.html
Normal file
67
plinth/templates/service.html
Normal file
@ -0,0 +1,67 @@
|
||||
{% 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 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
{% block pagetitle %}
|
||||
<h2>{{ service.name }}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block description %}
|
||||
{% for paragraph in description %}
|
||||
<p>{{ paragraph|safe }}</p>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block status %}
|
||||
<h3>Status</h3>
|
||||
<p class="running-status-parent">
|
||||
{% if service.is_running %}
|
||||
<span class="running-status active"></span>
|
||||
Service <i>{{ service.name }}</i> {% trans "is running" %}
|
||||
{% else %}
|
||||
<span class="running-status inactive"></span>
|
||||
Service <i>{{ service.name }}</i> {% trans "is not running" %}
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
||||
{% block diagnostics %}
|
||||
{% if diagnostics_module_name %}
|
||||
{% include "diagnostics_button.html" with module=diagnostics_module_name %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block configuration %}
|
||||
<h3>Configuration</h3>
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form|bootstrap }}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% endblock %}
|
||||
@ -37,6 +37,71 @@ def index(request):
|
||||
return HttpResponseRedirect(reverse('apps:index'))
|
||||
|
||||
|
||||
class ServiceView(FormView):
|
||||
"""A generic view for configuring simple modules."""
|
||||
service_id = None
|
||||
form_class = forms.ServiceForm
|
||||
template_name = 'service.html'
|
||||
# Set diagnostics_module_name to the module name to show diagnostics button
|
||||
diagnostics_module_name = ""
|
||||
# List of paragraphs describing the service
|
||||
description = ""
|
||||
|
||||
@property
|
||||
def success_url(self):
|
||||
return self.request.path
|
||||
|
||||
@property
|
||||
def service(self):
|
||||
if hasattr(self, '_service'):
|
||||
return self._service
|
||||
|
||||
if not self.service_id:
|
||||
raise ImproperlyConfigured("missing attribute: 'service_id'")
|
||||
service = plinth.service.services.get(self.service_id, None)
|
||||
if service is None:
|
||||
message = "Could not find service %s" % self.service_id
|
||||
raise ImproperlyConfigured(message)
|
||||
self._service = service
|
||||
return service
|
||||
|
||||
def get_initial(self):
|
||||
"""Return the status of the module to fill in the form."""
|
||||
return {'is_enabled': self.service.is_enabled(),
|
||||
'is_running': self.service.is_running()}
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Enable/disable a service and set messages."""
|
||||
old_status = form.initial
|
||||
new_status = form.cleaned_data
|
||||
|
||||
if old_status['is_enabled'] == new_status['is_enabled']:
|
||||
# TODO: find a more reliable/official way to check whether the
|
||||
# request has messages attached.
|
||||
if not self.request._messages._queued_messages:
|
||||
messages.info(self.request, _('Setting unchanged'))
|
||||
else:
|
||||
if new_status['is_enabled']:
|
||||
self.service.enable()
|
||||
messages.success(self.request, _('Application enabled'))
|
||||
else:
|
||||
self.service.disable()
|
||||
messages.success(self.request, _('Application disabled'))
|
||||
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
"""Add service to the context data."""
|
||||
context = super().get_context_data(*args, **kwargs)
|
||||
context['service'] = self.service
|
||||
if self.diagnostics_module_name:
|
||||
context['diagnostics_module_name'] = self.diagnostics_module_name
|
||||
if self.description:
|
||||
context['description'] = self.description
|
||||
return context
|
||||
|
||||
|
||||
# TODO: remove this view once owncloud is gone.
|
||||
class ConfigurationView(FormView):
|
||||
"""A generic view for configuring simple modules."""
|
||||
form_class = forms.ConfigurationForm
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user