diff --git a/plinth/modules/config/__init__.py b/plinth/modules/config/__init__.py
index 9d63ec457..af28b5a8f 100644
--- a/plinth/modules/config/__init__.py
+++ b/plinth/modules/config/__init__.py
@@ -156,9 +156,9 @@ def init():
# Register domain with Name Services module.
domainname = get_domainname()
if domainname:
- domain_added.send_robust(
- sender='config', domain_type='domainname', name=domainname,
- description=ugettext_lazy('Domain Name'), services='__all__')
+ domain_added.send_robust(sender='config',
+ domain_type='domain-type-static',
+ name=domainname, services='__all__')
def setup(helper, old_version=None):
diff --git a/plinth/modules/config/views.py b/plinth/modules/config/views.py
index f50814e61..b7ffb7f8c 100644
--- a/plinth/modules/config/views.py
+++ b/plinth/modules/config/views.py
@@ -82,7 +82,7 @@ def _apply_changes(request, old_status, new_status):
if old_status['domainname'] != new_status['domainname']:
try:
- set_domainname(new_status['domainname'])
+ set_domainname(new_status['domainname'], old_status['domainname'])
except Exception as exception:
messages.error(
request,
@@ -141,7 +141,7 @@ def set_hostname(hostname):
actions.superuser_run('domainname-change', [domainname])
-def set_domainname(domainname):
+def set_domainname(domainname, old_domainname):
"""Sets machine domain name to domainname"""
old_domainname = config.get_domainname()
@@ -156,8 +156,12 @@ def set_domainname(domainname):
new_domainname=domainname)
# Update domain registered with Name Services module.
- domain_removed.send_robust(sender='config', domain_type='domainname')
+ if old_domainname:
+ domain_removed.send_robust(sender='config',
+ domain_type='domain-type-static',
+ name=old_domainname)
+
if domainname:
- domain_added.send_robust(sender='config', domain_type='domainname',
- name=domainname, description=_('Domain Name'),
- services='__all__')
+ domain_added.send_robust(sender='config',
+ domain_type='domain-type-static',
+ name=domainname, services='__all__')
diff --git a/plinth/modules/dynamicdns/__init__.py b/plinth/modules/dynamicdns/__init__.py
index 884851e65..a06b343fc 100644
--- a/plinth/modules/dynamicdns/__init__.py
+++ b/plinth/modules/dynamicdns/__init__.py
@@ -87,9 +87,8 @@ def init():
current_status = get_status()
if current_status['enabled']:
domain_added.send_robust(
- sender='dynamicdns', domain_type='dynamicdnsservice',
- name=current_status['dynamicdns_domain'],
- description=_('Dynamic DNS Service'), services='__all__')
+ sender='dynamicdns', domain_type='domain-type-dynamic',
+ name=current_status['dynamicdns_domain'], services='__all__')
app.set_enabled(True)
diff --git a/plinth/modules/dynamicdns/views.py b/plinth/modules/dynamicdns/views.py
index 14729e741..af5160ada 100644
--- a/plinth/modules/dynamicdns/views.py
+++ b/plinth/modules/dynamicdns/views.py
@@ -156,15 +156,14 @@ def _apply_changes(request, old_status, new_status):
if old_status['enabled']:
domain_removed.send_robust(sender='dynamicdns',
- domain_type='dynamicdnsservice',
+ domain_type='domain-type-dynamic',
name=old_status['dynamicdns_domain'])
_run(['stop'])
if new_status['enabled']:
domain_added.send_robust(
- sender='dynamicdns', domain_type='dynamicdnsservice',
- name=new_status['dynamicdns_domain'],
- description=_('Dynamic DNS Service'), services='__all__')
+ sender='dynamicdns', domain_type='domain-type-dynamic',
+ name=new_status['dynamicdns_domain'], services='__all__')
_run(['start'])
messages.success(request, _('Configuration updated'))
diff --git a/plinth/modules/letsencrypt/__init__.py b/plinth/modules/letsencrypt/__init__.py
index 17a250706..882cae8e9 100644
--- a/plinth/modules/letsencrypt/__init__.py
+++ b/plinth/modules/letsencrypt/__init__.py
@@ -160,7 +160,7 @@ def on_domainname_change(sender, old_domainname, new_domainname, **kwargs):
def on_domain_added(sender, domain_type='', name='', description='',
services=None, **kwargs):
"""Obtain a certificate for the new domain"""
- if domain_type == 'hiddenservice':
+ if domain_type == 'domain-type-tor':
return False
# Check if a cert if already available
diff --git a/plinth/modules/letsencrypt/tests/test_domain_name_changes.py b/plinth/modules/letsencrypt/tests/test_domain_name_changes.py
index b83f66bd2..1a0f776f0 100644
--- a/plinth/modules/letsencrypt/tests/test_domain_name_changes.py
+++ b/plinth/modules/letsencrypt/tests/test_domain_name_changes.py
@@ -26,7 +26,7 @@ pytestmark = pytest.mark.usefixtures('needs_root', 'needs_sudo')
def test_add_onion_domain():
- assert not on_domain_added('test', 'hiddenservice', 'ddddd.onion')
+ assert not on_domain_added('test', 'domain-type-tor', 'ddddd.onion')
@pytest.mark.usefixtures('load_cfg')
diff --git a/plinth/modules/names/__init__.py b/plinth/modules/names/__init__.py
index 747e962da..39338f908 100644
--- a/plinth/modules/names/__init__.py
+++ b/plinth/modules/names/__init__.py
@@ -27,23 +27,15 @@ from plinth import cfg, menu
from plinth.signals import domain_added, domain_removed
from plinth.utils import format_lazy
+from . import components
from .manifest import backup # noqa, pylint: disable=unused-import
-SERVICES = (
- ('http', _('HTTP'), 80),
- ('https', _('HTTPS'), 443),
- ('ssh', _('SSH'), 22),
-)
-
version = 1
is_essential = True
name = _('Name Services')
-domain_types = {}
-domains = {}
-
logger = logging.getLogger(__name__)
manual_page = 'NameServices'
@@ -89,70 +81,27 @@ def on_domain_added(sender, domain_type, name='', description='',
if not domain_type:
return
- domain_types[domain_type] = description
-
if not name:
return
if not services:
services = []
- if domain_type not in domains:
- # new domain_type
- domains[domain_type] = {}
- domains[domain_type][name] = services
+ components.DomainName('domain-' + sender + '-' + name, name, domain_type,
+ services)
logger.info('Added domain %s of type %s with services %s', name,
domain_type, str(services))
def on_domain_removed(sender, domain_type, name='', **kwargs):
"""Remove domain from global list."""
- if domain_type in domains:
- if name == '': # remove all domains of this type
- domains[domain_type] = {}
- logger.info('Removed all domains of type %s', domain_type)
- elif name in domains[domain_type]:
- del domains[domain_type][name]
- logger.info('Removed domain %s of type %s', name, domain_type)
+ if name:
+ component_id = 'domain-' + sender + '-' + name
+ components.DomainName.get(component_id).remove()
+ logger.info('Removed domain %s of type %s', name, domain_type)
+ else:
+ for domain_name in components.DomainName.list():
+ if domain_name.domain_type.component_id == domain_type:
+ domain_name.remove()
-
-def get_domain_types():
- """Get list of domain_types."""
- return list(domain_types.keys())
-
-
-def get_description(domain_type):
- """Get description of a domain_type, if available."""
- if domain_type in domain_types:
- return domain_types[domain_type]
-
- return domain_type
-
-
-def get_domain(domain_type):
- """
- Get domain of type domain_type.
-
- This function is meant for use with single-domain domain_types. If there is
- more than one domain, any one of the domains may be returned.
- """
- if domain_type in domains and domains[domain_type]:
- return list(domains[domain_type].keys())[0]
-
- return None
-
-
-def get_enabled_services(domain_type, domain):
- """Get list of enabled services for a domain."""
- try:
- return domains[domain_type][domain]
- except KeyError:
- # domain_type or domain not registered
- return []
-
-
-def get_services_status(domain_type, domain):
- """Get list of whether each service is enabled for a domain."""
- enabled = get_enabled_services(domain_type, domain)
- return [
- enabled == '__all__' or service[0] in enabled for service in SERVICES
- ]
+ logger.info('Remove domain %s of type %s', domain_name.name,
+ domain_type)
diff --git a/plinth/modules/names/templates/names.html b/plinth/modules/names/templates/names.html
index df791e519..f94664e5f 100644
--- a/plinth/modules/names/templates/names.html
+++ b/plinth/modules/names/templates/names.html
@@ -26,31 +26,39 @@
- |
- {% for service in status.services %}
-
- {{ service }}
- |
- {% endfor %}
+ Type |
+ Domain Name |
+ Services |
+ |
- {% for name_service in status.name_services %}
-
-
- {{ name_service.type }}
- {{ name_service.name }}
- |
- {% for service in name_service.services_enabled %}
-
- {% if service %}
- {% trans "Enabled" %}
- {% else %}
- {% trans "Disabled" %}
- {% endif %}
- |
- {% endfor %}
-
+ {% for domain in status.domains|dictsort:"domain_type.display_name" %}
+
+ | {{ domain.domain_type.display_name }} |
+ {{ domain.name }} |
+ {{ domain.get_readable_services|join:', ' }} |
+
+
+ {% trans "Configure" %}
+
+ |
+
+ {% endfor %}
+
+ {% for domain_type in status.unused_domain_types %}
+
+ | {{ domain_type.display_name }} |
+ - |
+ - |
+
+
+ {% trans "Configure" %}
+
+ |
+
{% endfor %}
diff --git a/plinth/modules/names/tests/test_names.py b/plinth/modules/names/tests/test_names.py
index 32f17cfb0..a2af0887a 100644
--- a/plinth/modules/names/tests/test_names.py
+++ b/plinth/modules/names/tests/test_names.py
@@ -20,99 +20,39 @@ Tests for names module.
import pytest
-from .. import domain_types, domains
from .. import on_domain_added, on_domain_removed
-from .. import get_domain_types, get_description
-from .. import get_domain, get_enabled_services, get_services_status
+from ..components import DomainName, DomainType
@pytest.fixture(name='clean_domains')
def fixture_clean_domains():
"""Test fixture to start a test with clean domains list."""
- old_domain_types = dict(domain_types)
- old_domains = dict(domains)
- domain_types.clear()
- domains.clear()
- yield
- domain_types.clear()
- domains.clear()
- domain_types.update(old_domain_types)
- domains.update(old_domains)
+ DomainName._all = {} # pylint: disable=protected-access
@pytest.mark.usefixtures('clean_domains')
def test_on_domain_added():
"""Test adding a domain to the global list."""
on_domain_added('', '')
- assert '' not in domain_types
- assert '' not in domains
+ assert not DomainName.list()
- on_domain_added('', 'hiddenservice', 'ddddd.onion')
- on_domain_added('', 'hiddenservice', 'eeeee.onion')
- assert 'ddddd.onion' in domains['hiddenservice']
- assert 'eeeee.onion' in domains['hiddenservice']
+ DomainType('domain-type-tor', 'Tor Domain', 'torurl')
+ on_domain_added('tor', 'domain-type-tor', 'ddddd.onion')
+ on_domain_added('tor', 'domain-type-tor', 'eeeee.onion')
+ DomainName.get('domain-tor-ddddd.onion')
+ DomainName.get('domain-tor-eeeee.onion')
@pytest.mark.usefixtures('clean_domains')
def test_on_domain_removed():
"""Test removing a domain from the global list."""
- on_domain_added('', 'domainname', 'fffff')
- on_domain_removed('', 'domainname', 'fffff')
- assert 'fffff' not in domains['domainname']
-
- on_domain_added('', 'pagekite', 'ggggg.pagekite.me')
- on_domain_added('', 'pagekite', 'hhhhh.pagekite.me')
- on_domain_removed('', 'pagekite')
- assert 'ggggg.pagekite.me' not in domains['pagekite']
- assert 'hhhhh.pagekite.me' not in domains['pagekite']
+ DomainType('domain-type-tor', 'Tor Domain', 'torurl')
+ on_domain_added('tor', 'domain-type-tor', 'ddddd.onion')
+ on_domain_removed('tor', 'domain-type-tor', 'ddddd.onion')
+ with pytest.raises(KeyError):
+ DomainName.get('domain-tor-ddddd.onion')
# try to remove things that don't exist
on_domain_removed('', '')
- on_domain_removed('', 'domainname', 'iiiii')
-
-
-@pytest.mark.usefixtures('clean_domains')
-def test_get_domain_types():
- """Test getting domain types."""
- on_domain_added('', 'domainname')
- assert 'domainname' in get_domain_types()
-
-
-@pytest.mark.usefixtures('clean_domains')
-def test_get_description():
- """Test getting domain type description."""
- on_domain_added('', 'pagekite', '', 'Pagekite')
- assert get_description('pagekite') == 'Pagekite'
-
- assert get_description('asdfasdf') == 'asdfasdf'
-
-
-@pytest.mark.usefixtures('clean_domains')
-def test_get_domain():
- """Test getting a domain of domain_type."""
- on_domain_added('', 'hiddenservice', 'aaaaa.onion')
- assert get_domain('hiddenservice') == 'aaaaa.onion'
-
- assert get_domain('abcdef') is None
-
- on_domain_removed('', 'hiddenservice')
- assert get_domain('hiddenservice') is None
-
-
-@pytest.mark.usefixtures('clean_domains')
-def test_get_enabled_services():
- """Test getting enabled services for a domain."""
- on_domain_added('', 'domainname', 'bbbbb', '', ['http', 'https', 'ssh'])
- assert get_enabled_services('domainname',
- 'bbbbb') == ['http', 'https', 'ssh']
-
- assert get_enabled_services('xxxxx', 'yyyyy') == []
- assert get_enabled_services('domainname', 'zzzzz') == []
-
-
-@pytest.mark.usefixtures('clean_domains')
-def test_get_services_status():
- """Test getting whether each service is enabled for a domain."""
- on_domain_added('', 'pagekite', 'ccccc.pagekite.me', '', ['http', 'https'])
- assert get_services_status('pagekite', 'ccccc.pagekite.me') == \
- [True, True, False]
+ with pytest.raises(KeyError):
+ on_domain_removed('', 'domainname', 'iiiii')
diff --git a/plinth/modules/names/views.py b/plinth/modules/names/views.py
index ce0acd4ff..103768a33 100644
--- a/plinth/modules/names/views.py
+++ b/plinth/modules/names/views.py
@@ -19,12 +19,10 @@ FreedomBox app for name services.
"""
from django.template.response import TemplateResponse
-from django.utils.translation import ugettext as _
from plinth.modules import names
-from . import (SERVICES, get_description, get_domain, get_domain_types,
- get_services_status)
+from . import components
def index(request):
@@ -42,16 +40,11 @@ def index(request):
def get_status():
"""Get configured services per name."""
- name_services = []
- for domain_type in sorted(get_domain_types()):
- domain = get_domain(domain_type)
- name_services.append({
- 'type': get_description(domain_type),
- 'name': domain or _('Not Available'),
- 'services_enabled': get_services_status(domain_type, domain),
- })
+ domains = components.DomainName.list()
+ used_domain_types = {domain.domain_type for domain in domains}
+ unused_domain_types = [
+ domain_type for domain_type in components.DomainType.list().values()
+ if domain_type not in used_domain_types
+ ]
- return {
- 'services': [service[1] for service in SERVICES],
- 'name_services': name_services,
- }
+ return {'domains': domains, 'unused_domain_types': unused_domain_types}
diff --git a/plinth/modules/pagekite/utils.py b/plinth/modules/pagekite/utils.py
index b85ba2db3..1414bddd3 100644
--- a/plinth/modules/pagekite/utils.py
+++ b/plinth/modules/pagekite/utils.py
@@ -260,7 +260,8 @@ def update_names_module(initial_registration=False, enabled=None,
- enabled: Boolean (optional) whether PageKite is enabled
- kite_name: String (optional)
"""
- domain_removed.send_robust(sender='pagekite', domain_type='pagekite')
+ domain_removed.send_robust(sender='pagekite',
+ domain_type='domain-type-pagekite')
if enabled is None:
try:
@@ -284,9 +285,9 @@ def update_names_module(initial_registration=False, enabled=None,
kite_name = None
if initial_registration or (enabled and kite_name):
- domain_added.send_robust(sender='pagekite', domain_type='pagekite',
- name=kite_name, description=_('Pagekite'),
- services=enabled_services)
+ domain_added.send_robust(sender='pagekite',
+ domain_type='domain-type-pagekite',
+ name=kite_name, services=enabled_services)
if __name__ == "__main__":
diff --git a/plinth/modules/tor/__init__.py b/plinth/modules/tor/__init__.py
index 562bb5294..aebfc6833 100644
--- a/plinth/modules/tor/__init__.py
+++ b/plinth/modules/tor/__init__.py
@@ -27,7 +27,6 @@ from plinth import app as app_module
from plinth import menu
from plinth.daemon import Daemon
from plinth.modules.firewall.components import Firewall
-from plinth.modules.names import SERVICES
from plinth.modules.names.components import DomainType
from plinth.signals import domain_added, domain_removed
@@ -110,21 +109,13 @@ def init():
# Register hidden service name with Name Services module.
status = utils.get_status()
hostname = status['hs_hostname']
- hs_virtports = [port['virtport'] for port in status['hs_ports']]
+ services = [int(port['virtport']) for port in status['hs_ports']]
if status['enabled'] and status['is_running'] and \
status['hs_enabled'] and status['hs_hostname']:
- hs_services = []
- for service_type in SERVICES:
- if str(service_type[2]) in hs_virtports:
- hs_services.append(service_type[0])
- else:
- hostname = None
- hs_services = None
-
- domain_added.send_robust(
- sender='tor', domain_type='hiddenservice', name=hostname,
- description=_('Tor Hidden Service'), services=hs_services)
+ domain_added.send_robust(sender='tor',
+ domain_type='domain-type-tor',
+ name=hostname, services=services)
def setup(helper, old_version=None):
@@ -146,14 +137,13 @@ def update_hidden_service_domain(status=None):
if not status:
status = utils.get_status()
- domain_removed.send_robust(sender='tor', domain_type='hiddenservice')
+ domain_removed.send_robust(sender='tor', domain_type='domain-type-tor')
if status['enabled'] and status['is_running'] and \
status['hs_enabled'] and status['hs_hostname']:
- domain_added.send_robust(sender='tor', domain_type='hiddenservice',
- name=status['hs_hostname'],
- description=_('Tor Hidden Service'),
- services=status['hs_services'])
+ services = [int(port['virtport']) for port in status['hs_ports']]
+ domain_added.send_robust(sender='tor', domain_type='domain-type-tor',
+ name=status['hs_hostname'], services=services)
def diagnose():
diff --git a/plinth/modules/tor/templates/tor.html b/plinth/modules/tor/templates/tor.html
index 3f369c7aa..c4f6473f2 100644
--- a/plinth/modules/tor/templates/tor.html
+++ b/plinth/modules/tor/templates/tor.html
@@ -74,9 +74,7 @@
{{ status.hs_hostname }} |
{{ status.hs_status }} |
- {% for service in status.hs_services %}
- {{ service }}
- {% endfor %}
+ {{ status.hs_services|join:', ' }}
|
diff --git a/plinth/modules/tor/utils.py b/plinth/modules/tor/utils.py
index dc93d42b5..4b6b04b08 100644
--- a/plinth/modules/tor/utils.py
+++ b/plinth/modules/tor/utils.py
@@ -27,7 +27,7 @@ import augeas
from plinth import actions
from plinth.daemon import app_is_running
from plinth.modules import tor
-from plinth.modules.names import SERVICES
+from plinth.modules.names.components import DomainName
APT_SOURCES_URI_PATHS = ('/files/etc/apt/sources.list/*/uri',
'/files/etc/apt/sources.list.d/*/*/uri')
@@ -41,10 +41,13 @@ def get_status():
hs_info = status['hidden_service']
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])
+ if hs_info['hostname']:
+ try:
+ domain = DomainName.get('domain-tor-' + hs_info['hostname'])
+ except KeyError:
+ pass
+ else:
+ hs_services = domain.get_readable_services()
# Filter out obfs3/4 ports when bridge relay is disabled
ports = {