From 1eec1cf9cea2ea3f69f6927c20ef0fe06d2cc6e3 Mon Sep 17 00:00:00 2001 From: Joseph Nuthalapati Date: Fri, 24 Aug 2018 11:29:47 +0530 Subject: [PATCH] sharing: Allow directories to be publicly shared Signed-off-by: Joseph Nuthalapati Reviewed-by: James Valleroy --- actions/sharing | 32 +++++++++++++++++++++++------- plinth/modules/sharing/__init__.py | 9 +++++---- plinth/modules/sharing/forms.py | 22 ++++++++++++++++---- plinth/modules/sharing/views.py | 11 +++++----- 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/actions/sharing b/actions/sharing index baac364a7..d5fc0f6da 100755 --- a/actions/sharing +++ b/actions/sharing @@ -43,6 +43,8 @@ def parse_arguments(): add_parser.add_argument('--path', required=True, help='Disk path to share') add_parser.add_argument('--groups', nargs='*', help='List of groups that can access the share') + add_parser.add_argument('--is-public', default=False, required=False, + help='1 if public share else 0') remove_parser = subparsers.add_parser('remove', help='Remove an existing share') @@ -71,6 +73,7 @@ def subcommand_add(arguments): name = arguments.name path = arguments.path groups = arguments.groups + is_public = arguments.is_public url = '/share/' + name if not os.path.exists(APACHE_CONFIGURATION): @@ -90,15 +93,22 @@ def subcommand_add(arguments): aug.set('$conf/Location[last()]/directive[last() + 1]', 'Include') aug.set('$conf/Location[last()]/directive[last()]/arg', 'includes/freedombox-sharing.conf') - aug.set('$conf/Location[last()]/directive[last() + 1]', 'Include') - aug.set('$conf/Location[last()]/directive[last()]/arg', - 'includes/freedombox-single-sign-on.conf') - aug.set('$conf/Location[last()]/IfModule/arg', 'mod_auth_pubtkt.c') - aug.set('$conf/Location[last()]/IfModule/directive[1]', 'TKTAuthToken') - for group_name in groups: - aug.set('$conf/Location[last()]/IfModule/directive[1]/arg[last() + 1]', + if is_public != "true": + aug.set('$conf/Location[last()]/directive[last() + 1]', 'Include') + aug.set('$conf/Location[last()]/directive[last()]/arg', + 'includes/freedombox-single-sign-on.conf') + + aug.set('$conf/Location[last()]/IfModule/arg', 'mod_auth_pubtkt.c') + aug.set('$conf/Location[last()]/IfModule/directive[1]', 'TKTAuthToken') + for group_name in groups: + aug.set( + '$conf/Location[last()]/IfModule/directive[1]/arg[last() + 1]', group_name) + else: + aug.set('$conf/Location[last()]/directive[last() + 1]', 'Require') + aug.set('$conf/Location[last()]/directive[last()]/arg[1]', 'all') + aug.set('$conf/Location[last()]/directive[last()]/arg[2]', 'granted') aug.save() @@ -176,9 +186,17 @@ def _list(aug=None): for group in aug.match(location + '//directive["TKTAuthToken"]/arg'): groups.append(aug.get(group)) + def _is_public(): + """Must contain the line 'Require all granted'.""" + require = location + '//directive["Require"]' + return bool(aug.match(require)) and aug.get( + require + '/arg[1]') == 'all' and aug.get( + require + '/arg[2]') == 'granted' + for share in shares: if share['name'] == name: share['groups'] = groups + share['is_public'] = _is_public() return shares diff --git a/plinth/modules/sharing/__init__.py b/plinth/modules/sharing/__init__.py index 76fb6158d..843bce10a 100644 --- a/plinth/modules/sharing/__init__.py +++ b/plinth/modules/sharing/__init__.py @@ -69,11 +69,12 @@ def list_shares(): return json.loads(output)['shares'] -def add_share(name, path, groups): +def add_share(name, path, groups, is_public): """Add a new share by called the action script.""" - actions.superuser_run( - 'sharing', - ['add', '--name', name, '--path', path, '--groups'] + groups) + actions.superuser_run('sharing', [ + 'add', '--name', name, '--path', path, '--is-public', is_public, + '--groups' + ] + groups) def remove_share(name): diff --git a/plinth/modules/sharing/forms.py b/plinth/modules/sharing/forms.py index 23c029193..e788218fe 100644 --- a/plinth/modules/sharing/forms.py +++ b/plinth/modules/sharing/forms.py @@ -22,8 +22,8 @@ from django import forms from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ -from plinth.modules.users.forms import get_group_choices from plinth.modules import sharing +from plinth.modules.users.forms import get_group_choices class AddShareForm(forms.Form): @@ -39,11 +39,15 @@ class AddShareForm(forms.Form): label=_('Path to share'), strip=True, help_text=_( 'Disk path to a folder on this server that you intend to share.')) + is_public = forms.BooleanField( + label=_('Public share'), required=False, help_text=_( + 'Make files in this folder available to anyone with the link.')) + groups = forms.MultipleChoiceField( - widget=forms.CheckboxSelectMultiple, - label=_('User groups who can read the files in the share'), + widget=forms.CheckboxSelectMultiple, required=False, + label=_('User groups that can read the files in the share'), help_text=_( - 'Users who have these permissions will also be able to read the ' + 'Users of the selected user groups will be able to read the ' 'files in the share.')) def __init__(self, *args, **kwargs): @@ -63,3 +67,13 @@ class AddShareForm(forms.Form): raise ValidationError(_('A share with this name already exists.')) return name + + def clean(self): + """Check that at least one group is added for non-public shares.""" + super(AddShareForm, self).clean() + is_public = self.cleaned_data.get('is_public') + groups = self.cleaned_data.get('groups') + if not is_public and not groups: + raise forms.ValidationError( + _('Shares should be either public or shared with at least one group' + )) diff --git a/plinth/modules/sharing/views.py b/plinth/modules/sharing/views.py index ee6efbc38..9d4fcfc8f 100644 --- a/plinth/modules/sharing/views.py +++ b/plinth/modules/sharing/views.py @@ -61,8 +61,9 @@ class AddShareView(SuccessMessageMixin, FormView): def form_valid(self, form): """Add the share on valid form submission.""" - sharing.add_share(form.cleaned_data['name'], form.cleaned_data['path'], - form.cleaned_data['groups']) + data = form.cleaned_data + sharing.add_share(data['name'], data['path'], data['groups'], + str(data['is_public']).lower()) return super().form_valid(form) @@ -94,9 +95,9 @@ class EditShareView(SuccessMessageMixin, FormView): """Add the share on valid form submission.""" if form.initial != form.cleaned_data: sharing.remove_share(form.initial['name']) - sharing.add_share(form.cleaned_data['name'], - form.cleaned_data['path'], - form.cleaned_data['groups']) + data = form.cleaned_data + sharing.add_share(data['name'], data['path'], data['groups'], + str(data['is_public']).lower()) return super().form_valid(form)