names: Use new API in all apps

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2019-08-01 16:18:08 -07:00 committed by James Valleroy
parent b684b07d11
commit ba4afd2a09
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
14 changed files with 108 additions and 224 deletions

View File

@ -156,9 +156,9 @@ def init():
# Register domain with Name Services module. # Register domain with Name Services module.
domainname = get_domainname() domainname = get_domainname()
if domainname: if domainname:
domain_added.send_robust( domain_added.send_robust(sender='config',
sender='config', domain_type='domainname', name=domainname, domain_type='domain-type-static',
description=ugettext_lazy('Domain Name'), services='__all__') name=domainname, services='__all__')
def setup(helper, old_version=None): def setup(helper, old_version=None):

View File

@ -82,7 +82,7 @@ def _apply_changes(request, old_status, new_status):
if old_status['domainname'] != new_status['domainname']: if old_status['domainname'] != new_status['domainname']:
try: try:
set_domainname(new_status['domainname']) set_domainname(new_status['domainname'], old_status['domainname'])
except Exception as exception: except Exception as exception:
messages.error( messages.error(
request, request,
@ -141,7 +141,7 @@ def set_hostname(hostname):
actions.superuser_run('domainname-change', [domainname]) actions.superuser_run('domainname-change', [domainname])
def set_domainname(domainname): def set_domainname(domainname, old_domainname):
"""Sets machine domain name to domainname""" """Sets machine domain name to domainname"""
old_domainname = config.get_domainname() old_domainname = config.get_domainname()
@ -156,8 +156,12 @@ def set_domainname(domainname):
new_domainname=domainname) new_domainname=domainname)
# Update domain registered with Name Services module. # 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: if domainname:
domain_added.send_robust(sender='config', domain_type='domainname', domain_added.send_robust(sender='config',
name=domainname, description=_('Domain Name'), domain_type='domain-type-static',
services='__all__') name=domainname, services='__all__')

View File

@ -87,9 +87,8 @@ def init():
current_status = get_status() current_status = get_status()
if current_status['enabled']: if current_status['enabled']:
domain_added.send_robust( domain_added.send_robust(
sender='dynamicdns', domain_type='dynamicdnsservice', sender='dynamicdns', domain_type='domain-type-dynamic',
name=current_status['dynamicdns_domain'], name=current_status['dynamicdns_domain'], services='__all__')
description=_('Dynamic DNS Service'), services='__all__')
app.set_enabled(True) app.set_enabled(True)

View File

@ -156,15 +156,14 @@ def _apply_changes(request, old_status, new_status):
if old_status['enabled']: if old_status['enabled']:
domain_removed.send_robust(sender='dynamicdns', domain_removed.send_robust(sender='dynamicdns',
domain_type='dynamicdnsservice', domain_type='domain-type-dynamic',
name=old_status['dynamicdns_domain']) name=old_status['dynamicdns_domain'])
_run(['stop']) _run(['stop'])
if new_status['enabled']: if new_status['enabled']:
domain_added.send_robust( domain_added.send_robust(
sender='dynamicdns', domain_type='dynamicdnsservice', sender='dynamicdns', domain_type='domain-type-dynamic',
name=new_status['dynamicdns_domain'], name=new_status['dynamicdns_domain'], services='__all__')
description=_('Dynamic DNS Service'), services='__all__')
_run(['start']) _run(['start'])
messages.success(request, _('Configuration updated')) messages.success(request, _('Configuration updated'))

View File

@ -160,7 +160,7 @@ def on_domainname_change(sender, old_domainname, new_domainname, **kwargs):
def on_domain_added(sender, domain_type='', name='', description='', def on_domain_added(sender, domain_type='', name='', description='',
services=None, **kwargs): services=None, **kwargs):
"""Obtain a certificate for the new domain""" """Obtain a certificate for the new domain"""
if domain_type == 'hiddenservice': if domain_type == 'domain-type-tor':
return False return False
# Check if a cert if already available # Check if a cert if already available

View File

@ -26,7 +26,7 @@ pytestmark = pytest.mark.usefixtures('needs_root', 'needs_sudo')
def test_add_onion_domain(): 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') @pytest.mark.usefixtures('load_cfg')

View File

@ -27,23 +27,15 @@ from plinth import cfg, menu
from plinth.signals import domain_added, domain_removed from plinth.signals import domain_added, domain_removed
from plinth.utils import format_lazy from plinth.utils import format_lazy
from . import components
from .manifest import backup # noqa, pylint: disable=unused-import from .manifest import backup # noqa, pylint: disable=unused-import
SERVICES = (
('http', _('HTTP'), 80),
('https', _('HTTPS'), 443),
('ssh', _('SSH'), 22),
)
version = 1 version = 1
is_essential = True is_essential = True
name = _('Name Services') name = _('Name Services')
domain_types = {}
domains = {}
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
manual_page = 'NameServices' manual_page = 'NameServices'
@ -89,70 +81,27 @@ def on_domain_added(sender, domain_type, name='', description='',
if not domain_type: if not domain_type:
return return
domain_types[domain_type] = description
if not name: if not name:
return return
if not services: if not services:
services = [] services = []
if domain_type not in domains: components.DomainName('domain-' + sender + '-' + name, name, domain_type,
# new domain_type services)
domains[domain_type] = {}
domains[domain_type][name] = services
logger.info('Added domain %s of type %s with services %s', name, logger.info('Added domain %s of type %s with services %s', name,
domain_type, str(services)) domain_type, str(services))
def on_domain_removed(sender, domain_type, name='', **kwargs): def on_domain_removed(sender, domain_type, name='', **kwargs):
"""Remove domain from global list.""" """Remove domain from global list."""
if domain_type in domains: if name:
if name == '': # remove all domains of this type component_id = 'domain-' + sender + '-' + name
domains[domain_type] = {} components.DomainName.get(component_id).remove()
logger.info('Removed all domains of type %s', domain_type) logger.info('Removed domain %s of type %s', name, domain_type)
elif name in domains[domain_type]: else:
del domains[domain_type][name] for domain_name in components.DomainName.list():
logger.info('Removed domain %s of type %s', name, domain_type) if domain_name.domain_type.component_id == domain_type:
domain_name.remove()
logger.info('Remove domain %s of type %s', domain_name.name,
def get_domain_types(): domain_type)
"""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
]

View File

@ -26,31 +26,39 @@
<table class="table table-bordered table-condensed table-striped"> <table class="table table-bordered table-condensed table-striped">
<thead> <thead>
<tr> <tr>
<td></td> <th>Type</th>
{% for service in status.services %} <th>Domain Name</th>
<td> <th>Services</th>
<div class="text-center">{{ service }}</div> <th></th>
</td>
{% endfor %}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for name_service in status.name_services %} {% for domain in status.domains|dictsort:"domain_type.display_name" %}
<tr> <tr>
<td> <td>{{ domain.domain_type.display_name }}</td>
<b>{{ name_service.type }}</b><br> <td>{{ domain.name }}</td>
<i>{{ name_service.name }}</i> <td>{{ domain.get_readable_services|join:', ' }}</td>
</td> <td>
{% for service in name_service.services_enabled %} <a href="{% url domain.domain_type.configuration_url %}"
<td> role="button" class="btn btn-md btn-default">
{% if service %} {% trans "Configure" %}
<span class="label label-success">{% trans "Enabled" %}</span> </a>
{% else %} </td>
<span class="label label-warning">{% trans "Disabled" %}</span> </tr>
{% endif %} {% endfor %}
</td>
{% endfor %} {% for domain_type in status.unused_domain_types %}
</tr> <tr>
<td>{{ domain_type.display_name }}</td>
<td>-</td>
<td>-</td>
<td>
<a href="{% url domain_type.configuration_url %}"
role="button" class="btn btn-md btn-default">
{% trans "Configure" %}
</a>
</td>
</tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>

View File

@ -20,99 +20,39 @@ Tests for names module.
import pytest import pytest
from .. import domain_types, domains
from .. import on_domain_added, on_domain_removed from .. import on_domain_added, on_domain_removed
from .. import get_domain_types, get_description from ..components import DomainName, DomainType
from .. import get_domain, get_enabled_services, get_services_status
@pytest.fixture(name='clean_domains') @pytest.fixture(name='clean_domains')
def fixture_clean_domains(): def fixture_clean_domains():
"""Test fixture to start a test with clean domains list.""" """Test fixture to start a test with clean domains list."""
old_domain_types = dict(domain_types) DomainName._all = {} # pylint: disable=protected-access
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)
@pytest.mark.usefixtures('clean_domains') @pytest.mark.usefixtures('clean_domains')
def test_on_domain_added(): def test_on_domain_added():
"""Test adding a domain to the global list.""" """Test adding a domain to the global list."""
on_domain_added('', '') on_domain_added('', '')
assert '' not in domain_types assert not DomainName.list()
assert '' not in domains
on_domain_added('', 'hiddenservice', 'ddddd.onion') DomainType('domain-type-tor', 'Tor Domain', 'torurl')
on_domain_added('', 'hiddenservice', 'eeeee.onion') on_domain_added('tor', 'domain-type-tor', 'ddddd.onion')
assert 'ddddd.onion' in domains['hiddenservice'] on_domain_added('tor', 'domain-type-tor', 'eeeee.onion')
assert 'eeeee.onion' in domains['hiddenservice'] DomainName.get('domain-tor-ddddd.onion')
DomainName.get('domain-tor-eeeee.onion')
@pytest.mark.usefixtures('clean_domains') @pytest.mark.usefixtures('clean_domains')
def test_on_domain_removed(): def test_on_domain_removed():
"""Test removing a domain from the global list.""" """Test removing a domain from the global list."""
on_domain_added('', 'domainname', 'fffff') DomainType('domain-type-tor', 'Tor Domain', 'torurl')
on_domain_removed('', 'domainname', 'fffff') on_domain_added('tor', 'domain-type-tor', 'ddddd.onion')
assert 'fffff' not in domains['domainname'] on_domain_removed('tor', 'domain-type-tor', 'ddddd.onion')
with pytest.raises(KeyError):
on_domain_added('', 'pagekite', 'ggggg.pagekite.me') DomainName.get('domain-tor-ddddd.onion')
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']
# try to remove things that don't exist # try to remove things that don't exist
on_domain_removed('', '') on_domain_removed('', '')
on_domain_removed('', 'domainname', 'iiiii') with pytest.raises(KeyError):
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]

View File

@ -19,12 +19,10 @@ FreedomBox app for name services.
""" """
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.utils.translation import ugettext as _
from plinth.modules import names from plinth.modules import names
from . import (SERVICES, get_description, get_domain, get_domain_types, from . import components
get_services_status)
def index(request): def index(request):
@ -42,16 +40,11 @@ def index(request):
def get_status(): def get_status():
"""Get configured services per name.""" """Get configured services per name."""
name_services = [] domains = components.DomainName.list()
for domain_type in sorted(get_domain_types()): used_domain_types = {domain.domain_type for domain in domains}
domain = get_domain(domain_type) unused_domain_types = [
name_services.append({ domain_type for domain_type in components.DomainType.list().values()
'type': get_description(domain_type), if domain_type not in used_domain_types
'name': domain or _('Not Available'), ]
'services_enabled': get_services_status(domain_type, domain),
})
return { return {'domains': domains, 'unused_domain_types': unused_domain_types}
'services': [service[1] for service in SERVICES],
'name_services': name_services,
}

View File

@ -260,7 +260,8 @@ def update_names_module(initial_registration=False, enabled=None,
- enabled: Boolean (optional) whether PageKite is enabled - enabled: Boolean (optional) whether PageKite is enabled
- kite_name: String (optional) - 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: if enabled is None:
try: try:
@ -284,9 +285,9 @@ def update_names_module(initial_registration=False, enabled=None,
kite_name = None kite_name = None
if initial_registration or (enabled and kite_name): if initial_registration or (enabled and kite_name):
domain_added.send_robust(sender='pagekite', domain_type='pagekite', domain_added.send_robust(sender='pagekite',
name=kite_name, description=_('Pagekite'), domain_type='domain-type-pagekite',
services=enabled_services) name=kite_name, services=enabled_services)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -27,7 +27,6 @@ from plinth import app as app_module
from plinth import menu from plinth import menu
from plinth.daemon import Daemon from plinth.daemon import Daemon
from plinth.modules.firewall.components import Firewall from plinth.modules.firewall.components import Firewall
from plinth.modules.names import SERVICES
from plinth.modules.names.components import DomainType from plinth.modules.names.components import DomainType
from plinth.signals import domain_added, domain_removed from plinth.signals import domain_added, domain_removed
@ -110,21 +109,13 @@ def init():
# Register hidden service name with Name Services module. # Register hidden service name with Name Services module.
status = utils.get_status() status = utils.get_status()
hostname = status['hs_hostname'] 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 \ if status['enabled'] and status['is_running'] and \
status['hs_enabled'] and status['hs_hostname']: status['hs_enabled'] and status['hs_hostname']:
hs_services = [] domain_added.send_robust(sender='tor',
for service_type in SERVICES: domain_type='domain-type-tor',
if str(service_type[2]) in hs_virtports: name=hostname, services=services)
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)
def setup(helper, old_version=None): def setup(helper, old_version=None):
@ -146,14 +137,13 @@ def update_hidden_service_domain(status=None):
if not status: if not status:
status = utils.get_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 \ if status['enabled'] and status['is_running'] and \
status['hs_enabled'] and status['hs_hostname']: status['hs_enabled'] and status['hs_hostname']:
domain_added.send_robust(sender='tor', domain_type='hiddenservice', services = [int(port['virtport']) for port in status['hs_ports']]
name=status['hs_hostname'], domain_added.send_robust(sender='tor', domain_type='domain-type-tor',
description=_('Tor Hidden Service'), name=status['hs_hostname'], services=services)
services=status['hs_services'])
def diagnose(): def diagnose():

View File

@ -74,9 +74,7 @@
<td class="tor-hs-hostname">{{ status.hs_hostname }}</td> <td class="tor-hs-hostname">{{ status.hs_hostname }}</td>
<td class="tor-hs-status">{{ status.hs_status }}</td> <td class="tor-hs-status">{{ status.hs_status }}</td>
<td class="tor-hs-services"> <td class="tor-hs-services">
{% for service in status.hs_services %} {{ status.hs_services|join:', ' }}
{{ service }}
{% endfor %}
</td> </td>
</tr> </tr>
</tbody> </tbody>

View File

@ -27,7 +27,7 @@ import augeas
from plinth import actions from plinth import actions
from plinth.daemon import app_is_running from plinth.daemon import app_is_running
from plinth.modules import tor 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', APT_SOURCES_URI_PATHS = ('/files/etc/apt/sources.list/*/uri',
'/files/etc/apt/sources.list.d/*/*/uri') '/files/etc/apt/sources.list.d/*/*/uri')
@ -41,10 +41,13 @@ def get_status():
hs_info = status['hidden_service'] hs_info = status['hidden_service']
hs_services = [] hs_services = []
hs_virtports = [port['virtport'] for port in hs_info['ports']] if hs_info['hostname']:
for service_type in SERVICES: try:
if str(service_type[2]) in hs_virtports: domain = DomainName.get('domain-tor-' + hs_info['hostname'])
hs_services.append(service_type[0]) except KeyError:
pass
else:
hs_services = domain.get_readable_services()
# Filter out obfs3/4 ports when bridge relay is disabled # Filter out obfs3/4 ports when bridge relay is disabled
ports = { ports = {