mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-08-26 12:46:08 +00:00
radicale: Fix issue with parsing new configuration file
The latest version of radicale calendar server's configuration file does not parse with augeas. This is because it contains the following entry in [headers] section: Content-Security-Policy = default-src 'self'; object-src 'none' The semicolon is treated as comment by the lens which is not correct. Fix this by overriding comment_re in the lens. Tests: - Updated test case works when using augparse. - With the patch, latest upstream configuration file parses without errors. - Functional tests work for radicale in testing distribution. Without patch radicale fails to install. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
ae50ceaeb0
commit
2bd33ed428
@ -5,7 +5,6 @@ FreedomBox app for radicale.
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import augeas
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
@ -37,8 +36,6 @@ _description = [
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONFIG_FILE = '/etc/radicale/config'
|
|
||||||
|
|
||||||
|
|
||||||
class RadicaleApp(app_module.App):
|
class RadicaleApp(app_module.App):
|
||||||
"""FreedomBox app for Radicale."""
|
"""FreedomBox app for Radicale."""
|
||||||
@ -129,7 +126,7 @@ class RadicaleApp(app_module.App):
|
|||||||
if Version(package['new_version']) > Version('4~'):
|
if Version(package['new_version']) > Version('4~'):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
rights = get_rights_value()
|
rights = privileged.get_rights_value()
|
||||||
install(['radicale'], force_configuration='new')
|
install(['radicale'], force_configuration='new')
|
||||||
privileged.setup()
|
privileged.setup()
|
||||||
privileged.configure(rights)
|
privileged.configure(rights)
|
||||||
@ -140,28 +137,3 @@ class RadicaleApp(app_module.App):
|
|||||||
"""De-configure and uninstall the app."""
|
"""De-configure and uninstall the app."""
|
||||||
super().uninstall()
|
super().uninstall()
|
||||||
privileged.uninstall()
|
privileged.uninstall()
|
||||||
|
|
||||||
|
|
||||||
def load_augeas():
|
|
||||||
"""Prepares the augeas."""
|
|
||||||
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
|
||||||
augeas.Augeas.NO_MODL_AUTOLOAD)
|
|
||||||
|
|
||||||
# INI file lens
|
|
||||||
aug.set('/augeas/load/Puppet/lens', 'Puppet.lns')
|
|
||||||
aug.set('/augeas/load/Puppet/incl[last() + 1]', CONFIG_FILE)
|
|
||||||
|
|
||||||
aug.load()
|
|
||||||
return aug
|
|
||||||
|
|
||||||
|
|
||||||
def get_rights_value():
|
|
||||||
"""Returns the current Rights value."""
|
|
||||||
aug = load_augeas()
|
|
||||||
value = aug.get('/files' + CONFIG_FILE + '/rights/type')
|
|
||||||
|
|
||||||
if value == 'from_file':
|
|
||||||
# Default rights file is equivalent to owner_only.
|
|
||||||
value = 'owner_only'
|
|
||||||
|
|
||||||
return value
|
|
||||||
|
|||||||
@ -0,0 +1,45 @@
|
|||||||
|
(* Radicale module for Augeas
|
||||||
|
Based on Puppet lens.
|
||||||
|
|
||||||
|
Manage config file for http://radicale.org/
|
||||||
|
/etc/radicale/config is a standard INI File.
|
||||||
|
*)
|
||||||
|
|
||||||
|
|
||||||
|
module Radicale =
|
||||||
|
autoload xfm
|
||||||
|
|
||||||
|
(************************************************************************
|
||||||
|
* INI File settings
|
||||||
|
*
|
||||||
|
* /etc/radicale/config only supports "#" as commentary and "=" as separator
|
||||||
|
*************************************************************************)
|
||||||
|
let comment = IniFile.comment "#" "#"
|
||||||
|
let comment_re = /[#]/
|
||||||
|
let sep = IniFile.sep "=" "="
|
||||||
|
|
||||||
|
|
||||||
|
(************************************************************************
|
||||||
|
* ENTRY
|
||||||
|
* /etc/radicale/config uses standard INI File entries
|
||||||
|
*************************************************************************)
|
||||||
|
let entry = IniFile.entry_generic (Util.indent . key IniFile.entry_re) sep comment_re comment
|
||||||
|
|
||||||
|
|
||||||
|
(************************************************************************
|
||||||
|
* RECORD
|
||||||
|
* /etc/radicale/config uses standard INI File records
|
||||||
|
*************************************************************************)
|
||||||
|
let title = IniFile.indented_title IniFile.record_re
|
||||||
|
let record = IniFile.record title entry
|
||||||
|
|
||||||
|
|
||||||
|
(************************************************************************
|
||||||
|
* LENS & FILTER
|
||||||
|
* /etc/radicale/config uses standard INI File records
|
||||||
|
*************************************************************************)
|
||||||
|
let lns = IniFile.lns record comment
|
||||||
|
|
||||||
|
let filter = (incl "/etc/radicale/config")
|
||||||
|
|
||||||
|
let xfm = transform lns filter
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
module Test_radicale =
|
||||||
|
|
||||||
|
let conf = "
|
||||||
|
[server]
|
||||||
|
|
||||||
|
[encoding]
|
||||||
|
|
||||||
|
[well-known]
|
||||||
|
|
||||||
|
[auth]
|
||||||
|
|
||||||
|
[git]
|
||||||
|
|
||||||
|
[rights]
|
||||||
|
|
||||||
|
[storage]
|
||||||
|
|
||||||
|
[logging]
|
||||||
|
|
||||||
|
[headers]
|
||||||
|
Content-Security-Policy = default-src 'self'; object-src 'none'
|
||||||
|
|
||||||
|
"
|
||||||
|
|
||||||
|
test Radicale.lns get conf =
|
||||||
|
{}
|
||||||
|
{ "server"
|
||||||
|
{} }
|
||||||
|
{ "encoding"
|
||||||
|
{} }
|
||||||
|
{ "well-known"
|
||||||
|
{} }
|
||||||
|
{ "auth"
|
||||||
|
{} }
|
||||||
|
{ "git"
|
||||||
|
{} }
|
||||||
|
{ "rights"
|
||||||
|
{} }
|
||||||
|
{ "storage"
|
||||||
|
{} }
|
||||||
|
{ "logging"
|
||||||
|
{} }
|
||||||
|
{ "headers"
|
||||||
|
{ "Content-Security-Policy" = "default-src 'self'; object-src 'none'" }
|
||||||
|
{} }
|
||||||
|
|
||||||
|
test Radicale.lns put conf after
|
||||||
|
set "server/hosts" "127.0.0.1:5232, [::1]:5232";
|
||||||
|
set "server/base_prefix" "/radicale/";
|
||||||
|
set "well-known/caldav" "/radicale/%(user)s/caldav/";
|
||||||
|
set "well-known/cardav" "/radicale/%(user)s/carddav/";
|
||||||
|
set "auth/type" "remote_user";
|
||||||
|
set "rights/type" "owner_only";
|
||||||
|
set "headers/Content-Security-Policy" "default-src 'self'; object-src 'none'"
|
||||||
|
= "
|
||||||
|
[server]
|
||||||
|
|
||||||
|
hosts=127.0.0.1:5232, [::1]:5232
|
||||||
|
base_prefix=/radicale/
|
||||||
|
[encoding]
|
||||||
|
|
||||||
|
[well-known]
|
||||||
|
|
||||||
|
caldav=/radicale/%(user)s/caldav/
|
||||||
|
cardav=/radicale/%(user)s/carddav/
|
||||||
|
[auth]
|
||||||
|
|
||||||
|
type=remote_user
|
||||||
|
[git]
|
||||||
|
|
||||||
|
[rights]
|
||||||
|
|
||||||
|
type=owner_only
|
||||||
|
[storage]
|
||||||
|
|
||||||
|
[logging]
|
||||||
|
|
||||||
|
[headers]
|
||||||
|
Content-Security-Policy = default-src 'self'; object-src 'none'
|
||||||
|
|
||||||
|
"
|
||||||
@ -56,12 +56,24 @@ def load_augeas():
|
|||||||
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
# INI file lens
|
# INI file lens
|
||||||
aug.transform('Puppet', CONFIG_FILE)
|
aug.transform('Radicale', CONFIG_FILE)
|
||||||
aug.set('/augeas/context', '/files' + CONFIG_FILE)
|
aug.set('/augeas/context', '/files' + CONFIG_FILE)
|
||||||
aug.load()
|
aug.load()
|
||||||
return aug
|
return aug
|
||||||
|
|
||||||
|
|
||||||
|
def get_rights_value():
|
||||||
|
"""Returns the current Rights value."""
|
||||||
|
aug = load_augeas()
|
||||||
|
value = aug.get('rights/type')
|
||||||
|
|
||||||
|
if value == 'from_file':
|
||||||
|
# Default rights file is equivalent to owner_only.
|
||||||
|
value = 'owner_only'
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
@privileged
|
@privileged
|
||||||
def uninstall():
|
def uninstall():
|
||||||
"""Remove all radicale collections."""
|
"""Remove all radicale collections."""
|
||||||
|
|||||||
@ -8,7 +8,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
|
|
||||||
from plinth.views import AppView
|
from plinth.views import AppView
|
||||||
|
|
||||||
from . import get_rights_value, privileged
|
from . import privileged
|
||||||
from .forms import RadicaleForm
|
from .forms import RadicaleForm
|
||||||
|
|
||||||
|
|
||||||
@ -20,13 +20,13 @@ class RadicaleAppView(AppView):
|
|||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
"""Return the values to fill in the form."""
|
"""Return the values to fill in the form."""
|
||||||
initial = super().get_initial()
|
initial = super().get_initial()
|
||||||
initial['access_rights'] = get_rights_value()
|
initial['access_rights'] = privileged.get_rights_value()
|
||||||
return initial
|
return initial
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
"""Change the access control of Radicale service."""
|
"""Change the access control of Radicale service."""
|
||||||
data = form.cleaned_data
|
data = form.cleaned_data
|
||||||
if get_rights_value() != data['access_rights']:
|
if privileged.get_rights_value() != data['access_rights']:
|
||||||
privileged.configure(data['access_rights'])
|
privileged.configure(data['access_rights'])
|
||||||
messages.success(self.request,
|
messages.success(self.request,
|
||||||
_('Access rights configuration updated'))
|
_('Access rights configuration updated'))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user