mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-03-11 09:04:54 +00:00
ejabberd: Add multi-select form for domains
Choices includes all of the available domain names in the system, as well as any domains that are in ejabberd configuration. Tests: - Disable a domain. It is removed from ejabberd config. - Enable a domain. It is added to ejabberd config. - Enable all name services. Run ejabberd functional tests and observe that they pass. Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
parent
7d4c3dbb67
commit
1a39212313
@ -70,11 +70,19 @@ def parse_arguments():
|
||||
hostname_change.add_argument('--old-hostname', help='Previous hostname')
|
||||
hostname_change.add_argument('--new-hostname', help='New hostname')
|
||||
|
||||
# Add a domain name to ejabberd
|
||||
# Manage domain names
|
||||
subparsers.add_parser('get-domains',
|
||||
help='Get all configured domains in JSON format')
|
||||
|
||||
add_domain = subparsers.add_parser('add-domain',
|
||||
help='Add a domain name to ejabberd')
|
||||
add_domain.add_argument('--domainname', help='New domain name')
|
||||
|
||||
set_domains = subparsers.add_parser('set-domains',
|
||||
help='Set list of ejabberd domains')
|
||||
set_domains.add_argument('--domains', nargs='+',
|
||||
help='One or more domain names')
|
||||
|
||||
# Configure STUN/TURN server for use with ejabberd
|
||||
turn = subparsers.add_parser(
|
||||
'configure-turn', help='Configure a TURN server for use with ejabberd')
|
||||
@ -236,8 +244,23 @@ def subcommand_change_hostname(arguments):
|
||||
EJABBERD_BACKUP_NEW)
|
||||
|
||||
|
||||
def subcommand_get_domains(_):
|
||||
"""Get all configured domains."""
|
||||
if not shutil.which('ejabberdctl'):
|
||||
print('ejabberdctl not found. Is ejabberd installed?')
|
||||
return
|
||||
|
||||
with open(EJABBERD_CONFIG, 'r') as file_handle:
|
||||
conf = yaml.load(file_handle)
|
||||
|
||||
print(json.dumps(conf['hosts']))
|
||||
|
||||
|
||||
def subcommand_add_domain(arguments):
|
||||
"""Update ejabberd with new domainname"""
|
||||
"""Update ejabberd with new domainname.
|
||||
|
||||
Restarting ejabberd is handled by letsencrypt-ejabberd component.
|
||||
"""
|
||||
if not shutil.which('ejabberdctl'):
|
||||
print('ejabberdctl not found. Is ejabberd installed?')
|
||||
return
|
||||
@ -255,6 +278,26 @@ def subcommand_add_domain(arguments):
|
||||
with open(EJABBERD_CONFIG, 'w') as file_handle:
|
||||
yaml.dump(conf, file_handle)
|
||||
|
||||
# Restarting ejabberd is handled by letsencrypt-ejabberd component.
|
||||
|
||||
|
||||
def subcommand_set_domains(arguments):
|
||||
"""Set list of ejabberd domains.
|
||||
|
||||
Restarting ejabberd is handled by letsencrypt-ejabberd component.
|
||||
"""
|
||||
if not shutil.which('ejabberdctl'):
|
||||
print('ejabberdctl not found. Is ejabberd installed?')
|
||||
return
|
||||
|
||||
with open(EJABBERD_CONFIG, 'r') as file_handle:
|
||||
conf = yaml.load(file_handle)
|
||||
|
||||
conf['hosts'] = arguments.domains
|
||||
|
||||
with open(EJABBERD_CONFIG, 'w') as file_handle:
|
||||
yaml.dump(conf, file_handle)
|
||||
|
||||
|
||||
def subcommand_mam(argument):
|
||||
"""Enable, disable, or get status of Message Archive Management (MAM)."""
|
||||
|
||||
@ -158,22 +158,6 @@ def setup(helper, old_version=None):
|
||||
update_turn_configuration(configuration, force=True)
|
||||
|
||||
|
||||
def get_domains():
|
||||
"""Return the list of domains that ejabberd is interested in.
|
||||
|
||||
XXX: Retrieve the list from ejabberd configuration.
|
||||
|
||||
"""
|
||||
if app.needs_setup():
|
||||
return []
|
||||
|
||||
domain_name = config.get_domainname()
|
||||
if domain_name:
|
||||
return [domain_name]
|
||||
|
||||
return []
|
||||
|
||||
|
||||
def on_pre_hostname_change(sender, old_hostname, new_hostname, **kwargs):
|
||||
"""
|
||||
Backup ejabberd database before hostname is changed.
|
||||
@ -202,19 +186,39 @@ def on_post_hostname_change(sender, old_hostname, new_hostname, **kwargs):
|
||||
], run_in_background=True)
|
||||
|
||||
|
||||
def get_domains():
|
||||
"""Return the list of domains configured for ejabberd.
|
||||
"""
|
||||
if app.needs_setup():
|
||||
return []
|
||||
|
||||
output = actions.superuser_run('ejabberd', ['get-domains'])
|
||||
return json.loads(output)
|
||||
|
||||
|
||||
def on_domain_added(sender, domain_type, name='', description='',
|
||||
services=None, **kwargs):
|
||||
"""Update ejabberd config after domain name change."""
|
||||
if not name or app.needs_setup():
|
||||
return
|
||||
|
||||
conf = actions.superuser_run('ejabberd', ['get-configuration'])
|
||||
conf = json.loads(conf)
|
||||
if name not in conf['domains']:
|
||||
domains = get_domains()
|
||||
if name not in domains:
|
||||
actions.superuser_run('ejabberd', ['add-domain', '--domainname', name])
|
||||
app.get_component('letsencrypt-ejabberd').setup_certificates()
|
||||
|
||||
|
||||
def set_domains(domains):
|
||||
"""Configure ejabberd to have this list of domains."""
|
||||
if not domains or app.needs_setup():
|
||||
return
|
||||
|
||||
commands = ['set-domains', '--domains']
|
||||
commands.extend(domains)
|
||||
actions.superuser_run('ejabberd', commands)
|
||||
app.get_component('letsencrypt-ejabberd').setup_certificates()
|
||||
|
||||
|
||||
def update_turn_configuration(config: TurnConfiguration, managed=True,
|
||||
force=False):
|
||||
"""Update ejabberd's STUN/TURN server configuration."""
|
||||
|
||||
@ -8,12 +8,21 @@ from django.urls import reverse_lazy
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from plinth import cfg
|
||||
from plinth.modules import ejabberd
|
||||
from plinth.modules.coturn.forms import turn_uris_validator
|
||||
from plinth.utils import format_lazy
|
||||
|
||||
|
||||
class EjabberdForm(forms.Form):
|
||||
"""Ejabberd configuration form."""
|
||||
domain_names = forms.MultipleChoiceField(
|
||||
label=_('Domain names'), widget=forms.CheckboxSelectMultiple,
|
||||
help_text=_(
|
||||
'Domains to be used by ejabberd. "localhost" is always included, '
|
||||
'so it is not shown here. Note that user accounts are unique for '
|
||||
'each domain, and migrating users to a new domain name is not yet '
|
||||
'implemented.'), choices=[])
|
||||
|
||||
MAM_enabled = forms.BooleanField(
|
||||
label=_('Enable Message Archive Management'), required=False,
|
||||
help_text=format_lazy(
|
||||
@ -43,6 +52,18 @@ class EjabberdForm(forms.Form):
|
||||
help_text=_('Shared secret used to compute passwords for the '
|
||||
'TURN server.'))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Start with any existing domains from ejabberd configuration.
|
||||
domains = set(ejabberd.get_domains())
|
||||
|
||||
# Add other domains that can be configured.
|
||||
from plinth.modules.names.components import DomainName
|
||||
domains |= DomainName.list_names()
|
||||
|
||||
self.fields['domain_names'].choices = zip(domains, domains)
|
||||
|
||||
def clean_turn_uris(self):
|
||||
"""Normalize newlines in URIs."""
|
||||
data = self.cleaned_data['turn_uris']
|
||||
|
||||
@ -8,8 +8,7 @@ from plinth.tests import functional
|
||||
|
||||
pytestmark = [pytest.mark.apps, pytest.mark.ejabberd]
|
||||
|
||||
# TODO Check service
|
||||
# TODO Check domain name display
|
||||
# TODO Check domain name displayed in description
|
||||
|
||||
|
||||
class TestEjabberdApp(functional.BaseAppTests):
|
||||
@ -17,6 +16,29 @@ class TestEjabberdApp(functional.BaseAppTests):
|
||||
has_service = True
|
||||
has_web = False
|
||||
|
||||
@pytest.fixture(scope='module', autouse=True)
|
||||
def fixture_background(self, session_browser):
|
||||
"""Login, install, and enable the app."""
|
||||
functional.login(session_browser)
|
||||
functional.install(session_browser, self.app_name)
|
||||
functional.app_enable(session_browser, self.app_name)
|
||||
yield
|
||||
functional.login(session_browser)
|
||||
functional.app_disable(session_browser, self.app_name)
|
||||
|
||||
def test_add_remove_domain(self, session_browser):
|
||||
"""Test adding and removing a domain."""
|
||||
functional.app_enable(session_browser, 'ejabberd')
|
||||
_enable_domain(session_browser, 'freedombox.local')
|
||||
|
||||
_disable_domain(session_browser, 'freedombox.local')
|
||||
assert not _is_domain_enabled(session_browser, 'freedombox.local')
|
||||
assert functional.service_is_running(session_browser, 'ejabberd')
|
||||
|
||||
_enable_domain(session_browser, 'freedombox.local')
|
||||
assert _is_domain_enabled(session_browser, 'freedombox.local')
|
||||
assert functional.service_is_running(session_browser, 'ejabberd')
|
||||
|
||||
def test_message_archive_management(self, session_browser):
|
||||
"""Test enabling message archive management."""
|
||||
functional.app_enable(session_browser, 'ejabberd')
|
||||
@ -39,6 +61,29 @@ class TestEjabberdApp(functional.BaseAppTests):
|
||||
_jsxc_assert_has_contact(session_browser)
|
||||
|
||||
|
||||
def _enable_domain(browser, domain):
|
||||
"""Add domain name to Ejabberd configuration."""
|
||||
functional.nav_to_module(browser, 'ejabberd')
|
||||
checkbox = browser.find_by_value(domain).first
|
||||
checkbox.check()
|
||||
functional.submit(browser, form_class='form-configuration')
|
||||
|
||||
|
||||
def _disable_domain(browser, domain):
|
||||
"""Remove domain name from Ejabberd configuration."""
|
||||
functional.nav_to_module(browser, 'ejabberd')
|
||||
checkbox = browser.find_by_value(domain).first
|
||||
checkbox.uncheck()
|
||||
functional.submit(browser, form_class='form-configuration')
|
||||
|
||||
|
||||
def _is_domain_enabled(browser, domain):
|
||||
"""Return whether the domain name is enabled."""
|
||||
functional.nav_to_module(browser, 'ejabberd')
|
||||
checkbox = browser.find_by_value(domain).first
|
||||
return checkbox.checked
|
||||
|
||||
|
||||
def _enable_message_archive_management(browser):
|
||||
"""Enable Message Archive Management in Ejabberd."""
|
||||
functional.nav_to_module(browser, 'ejabberd')
|
||||
|
||||
@ -24,6 +24,7 @@ class EjabberdAppView(AppView):
|
||||
"""Initial data to fill in the form."""
|
||||
config, managed = ejabberd.get_turn_configuration()
|
||||
return super().get_initial() | {
|
||||
'domain_names': ejabberd.get_domains(),
|
||||
'MAM_enabled': self.is_MAM_enabled(),
|
||||
'enable_managed_turn': managed,
|
||||
'turn_uris': '\n'.join(config.uris),
|
||||
@ -37,6 +38,11 @@ class EjabberdAppView(AppView):
|
||||
context['domainname'] = domains[0] if domains else None
|
||||
return context
|
||||
|
||||
@staticmethod
|
||||
def _handle_domain_names_configuration(new_config):
|
||||
"""Update list of domain names in configuration."""
|
||||
ejabberd.set_domains(new_config['domain_names'])
|
||||
|
||||
@staticmethod
|
||||
def _handle_turn_configuration(old_config, new_config):
|
||||
if not new_config['enable_managed_turn']:
|
||||
@ -72,6 +78,11 @@ class EjabberdAppView(AppView):
|
||||
return old_config[prop] != new_config[prop]
|
||||
|
||||
is_changed = False
|
||||
|
||||
if changed('domain_names'):
|
||||
self._handle_domain_names_configuration(new_config)
|
||||
is_changed = True
|
||||
|
||||
if changed('MAM_enabled'):
|
||||
self._handle_MAM_configuration(old_config, new_config)
|
||||
is_changed = True
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user