roundcube: Add setting for local connection only

When this option is enabled, it would make the interface easy to work with. This
is likely what most users would want. Don't break things for users who have
already installed roundcube and ensure that local only is disable for them.

Tests:

- Install roundcube without the patch. Disable the app. Apply patch. Restart
service. Notice that roundcube is not re-enabled.

- Install roundcube without the patch. Apply patch. Restart service. Notice that
roundcube configuration /etc/roundcube/config.inc.php file has been updated and
include_once() at the end has been added. The file
/etc/roundcube/freedombox-config.php has been added. Local only option is
disabled.

- Install roundcube freshly with the patch. Local only option is enabled. Open
interface. Notice that server option is not presented.

- Disable local only option and notice that server field is shown in the
interface.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
[jvalleroy: Fix comment]
Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2022-01-26 16:39:08 -08:00 committed by James Valleroy
parent 9a2d66c62f
commit affffddf36
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
5 changed files with 130 additions and 5 deletions

View File

@ -5,9 +5,14 @@ Configuration helper for Roundcube server.
"""
import argparse
import json
import pathlib
import re
from plinth import action_utils
_config_file = pathlib.Path('/etc/roundcube/freedombox-config.php')
def parse_arguments():
"""Return parsed command line arguments as dictionary."""
@ -16,6 +21,11 @@ def parse_arguments():
subparsers.add_parser('pre-install',
help='Perform Roundcube pre-install configuration')
subparsers.add_parser('setup', help='Setup basic configuration')
subparsers.add_parser('get-config', help='Print current configuration')
subparser = subparsers.add_parser('set-config', help='Set configuration')
subparser.add_argument('--local-only', choices=['True', 'False'],
help='Set current configuration')
subparsers.required = True
return parser.parse_args()
@ -29,6 +39,51 @@ def subcommand_pre_install(_):
])
def subcommand_setup(_):
"""Add FreedomBox configuration and include from main configuration."""
if not _config_file.exists():
_config_file.write_text('<?php\n')
base_config = pathlib.Path('/etc/roundcube/config.inc.php')
lines = base_config.read_text().splitlines()
exists = any((str(_config_file) in line for line in lines))
if not exists:
lines.append(f'include_once("{_config_file}");\n')
base_config.write_text('\n'.join(lines))
def subcommand_get_config(_):
"""Print the current configuration as JSON."""
pattern = r'\s*\$config\[\s*\'([^\']*)\'\s*\]\s*=\s*\'([^\']*)\'\s*;'
_config = {}
try:
for line in _config_file.read_text().splitlines():
match = re.match(pattern, line)
if match:
_config[match.group(1)] = match.group(2)
except FileNotFoundError:
pass
local_only = _config.get('default_host') == 'localhost'
print(json.dumps({'local_only': local_only}))
def subcommand_set_config(arguments):
"""Set the configuration."""
config = '<?php\n'
if arguments.local_only == 'True':
config = '''<?php
$config['default_host'] = 'localhost';
$config['mail_domain'] = '%n';
$config['smtp_server'] = 'localhost';
$config['smtp_port'] = 25;
$config['smtp_helo_host'] = 'localhost';
'''
_config_file.write_text(config)
def main():
"""Parse arguments and perform all duties."""
arguments = parse_arguments()

View File

@ -3,6 +3,8 @@
FreedomBox app to configure Roundcube.
"""
import json
from django.utils.translation import gettext_lazy as _
from plinth import actions
@ -42,7 +44,7 @@ class RoundcubeApp(app_module.App):
app_id = 'roundcube'
_version = 1
_version = 2
def __init__(self):
"""Create components for the app."""
@ -94,7 +96,10 @@ def setup(helper, old_version=None):
"""Install and configure the module."""
helper.call('pre', actions.superuser_run, 'roundcube', ['pre-install'])
app.setup(old_version)
helper.call('post', app.enable)
helper.call('post', actions.superuser_run, 'roundcube', ['setup'])
if old_version == 0:
set_config(local_only=True)
helper.call('post', app.enable)
def force_upgrade(helper, packages):
@ -109,3 +114,16 @@ def force_upgrade(helper, packages):
app.get_component('webserver-roundcube-freedombox').enable()
return True
def get_config():
"""Return Rouncube configuration."""
value = actions.superuser_run('roundcube', ['get-config'])
return json.loads(value)
def set_config(local_only):
"""Set whether only local server should be allowed."""
actions.superuser_run('roundcube',
['set-config', '--local-only',
str(local_only)])

View File

@ -0,0 +1,19 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Configuration forms for roundcube.
"""
from django import forms
from django.utils.translation import gettext_lazy as _
from plinth import cfg
from plinth.utils import format_lazy
class RoundcubeForm(forms.Form):
"""Roundcube configuration form."""
local_only = forms.BooleanField(
label=_('Use only the local mail server'), help_text=format_lazy(
_('When enabled, text box for server input is removed from login '
'page and users can only read and send mails from this '
'{box_name}.'), box_name=_(cfg.box_name)), required=False)

View File

@ -5,9 +5,8 @@ URLs for the Roundcube module.
from django.urls import re_path
from plinth.views import AppView
from .views import RoundcubeAppView
urlpatterns = [
re_path(r'^apps/roundcube/$', AppView.as_view(app_id='roundcube'),
name='index')
re_path(r'^apps/roundcube/$', RoundcubeAppView.as_view(), name='index')
]

View File

@ -0,0 +1,34 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Views for roundcube.
"""
from django.contrib import messages
from django.utils.translation import gettext_lazy as _
from plinth.modules import roundcube
from plinth.views import AppView
from .forms import RoundcubeForm
class RoundcubeAppView(AppView):
"""Roundcube configuration page."""
app_id = 'roundcube'
form_class = RoundcubeForm
def get_initial(self):
"""Return the values to fill in the form."""
initial = super().get_initial()
initial['local_only'] = roundcube.get_config()['local_only']
return initial
def form_valid(self, form):
"""Change the config of Roundcube app."""
old_data = form.initial
data = form.cleaned_data
if old_data['local_only'] != data['local_only']:
roundcube.set_config(data['local_only'])
messages.success(self.request, _('Configuration updated'))
return super().form_valid(form)