coturn: Use privileged decorator for actions

Tests:

- Initial setup of coturn succeeds
  - Configuration file is created and required configuration is set.
  - Coturn is restarted
- Coturn configuration is shown on app page.
- Changing the domain succeeds and coturn configuration reflects the new domain.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2022-08-26 16:21:20 -07:00 committed by James Valleroy
parent 7ff050511c
commit 013caa28bc
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
3 changed files with 18 additions and 54 deletions

View File

@ -1,16 +1,12 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
FreedomBox app to configure Coturn server.
"""
"""FreedomBox app to configure Coturn server."""
import json
import logging
import pathlib
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from plinth import actions
from plinth import app as app_module
from plinth import menu
from plinth.daemon import Daemon
@ -23,7 +19,7 @@ from plinth.modules.users.components import UsersAndGroups
from plinth.package import Packages
from plinth.utils import format_lazy
from . import manifest
from . import manifest, privileged
_description = [
_('Coturn is a server to facilitate audio/video calls and conferences by '
@ -109,7 +105,7 @@ class CoturnApp(app_module.App):
def setup(self, old_version):
"""Install and configure the app."""
super().setup(old_version)
actions.superuser_run('coturn', ['setup'])
privileged.setup()
if old_version == 0:
self.enable()
@ -151,14 +147,13 @@ def get_domains():
def set_domain(domain):
"""Set the TLS domain by writing a file to data directory."""
if domain:
actions.superuser_run('coturn', ['set-domain', domain])
privileged.set_domain(domain)
notify_configuration_change()
def get_config():
"""Return the coturn server configuration."""
output = actions.superuser_run('coturn', ['get-config'])
config = json.loads(output)
config = privileged.get_config()
return TurnConfiguration(config['realm'], [], config['static_auth_secret'])

52
actions/coturn → plinth/modules/coturn/privileged.py Executable file → Normal file
View File

@ -1,11 +1,6 @@
#!/usr/bin/python3
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Configuration helper for Coturn daemon.
"""
"""Configuration helper for Coturn daemon."""
import argparse
import json
import pathlib
import random
import shutil
@ -14,31 +9,18 @@ import string
import augeas
from plinth import action_utils
from plinth.actions import privileged
CONFIG_FILE = pathlib.Path('/etc/coturn/freedombox.conf')
def parse_arguments():
"""Return parsed command line arguments as dictionary."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
subparsers.add_parser('setup', help='Setup Coturn server')
subparsers.add_parser('get-config',
help='Return the current configuration')
subparser = subparsers.add_parser('set-domain', help='Set the TLS domain')
subparser.add_argument('domain_name', help='TLS domain name to set')
subparsers.required = True
return parser.parse_args()
def _key_path(key):
"""Return the augeas path for a key."""
return '/files' + str(CONFIG_FILE) + '/' + key
def subcommand_setup(_):
@privileged
def setup():
"""Setup Coturn server."""
CONFIG_FILE.parent.mkdir(exist_ok=True)
if not CONFIG_FILE.exists():
@ -75,25 +57,26 @@ def subcommand_setup(_):
action_utils.service_try_restart('coturn')
def subcommand_get_config(_):
"""Return the current configuration in JSON format."""
@privileged
def get_config() -> dict[str, str]:
"""Return the current configuration."""
aug = augeas_load()
config = {
'static_auth_secret': aug.get(_key_path('static-auth-secret')),
'realm': aug.get(_key_path('realm')),
}
print(json.dumps(config))
return config
def subcommand_set_domain(arguments):
@privileged
def set_domain(domain_name: str):
"""Set the TLS domain.
This value is usually not stored. So, set realm value even though it is not
needed to set realm for REST API based authentication.
"""
aug = augeas_load()
aug.set(_key_path('realm'), arguments.domain_name)
aug.set(_key_path('realm'), domain_name)
aug.save()
@ -106,16 +89,3 @@ def augeas_load():
aug.load()
return aug
def main():
"""Parse arguments and perform all duties."""
arguments = parse_arguments()
subcommand = arguments.subcommand.replace('-', '_')
subcommand_method = globals()['subcommand_' + subcommand]
subcommand_method(arguments)
if __name__ == '__main__':
main()

View File

@ -1,7 +1,5 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Views for Coturn app.
"""
"""Views for Coturn app."""
from django.contrib import messages
from django.utils.translation import gettext_lazy as _
@ -15,6 +13,7 @@ from . import forms
class CoturnAppView(views.AppView):
"""Serve configuration page."""
app_id = 'coturn'
template_name = 'coturn.html'
form_class = forms.CoturnForm