diff --git a/actions/users b/actions/users index a4f93bc72..794aa87cd 100755 --- a/actions/users +++ b/actions/users @@ -346,17 +346,6 @@ def subcommand_remove_user_from_group(arguments): flush_cache() -def subcommand_get_all_groups(_): - """Get all user groups""" - get_groups = "getent group".split() - cut_names = "cut -d: -f1".split() - groups = subprocess.Popen(get_groups, stdout=subprocess.PIPE, shell=False) - trimmed_groups = subprocess.Popen(cut_names, stdin=groups.stdout, - stdout=subprocess.PIPE, shell=False) - groups.stdout.close() - print(trimmed_groups.communicate()[0].decode()) - - def flush_cache(): """Flush nscd cache.""" _run(['nscd', '--invalidate=passwd']) diff --git a/data/etc/apache2/conf-available/tt-rss-plinth.conf b/data/etc/apache2/conf-available/tt-rss-plinth.conf index 9e8c6e375..675ec36a7 100644 --- a/data/etc/apache2/conf-available/tt-rss-plinth.conf +++ b/data/etc/apache2/conf-available/tt-rss-plinth.conf @@ -8,12 +8,12 @@ Alias /tt-rss-app /usr/share/tt-rss/www Include includes/freedombox-single-sign-on.conf - TKTAuthToken "newsfeed" "admin" + TKTAuthToken "feed-reader" "admin" Include includes/freedombox-auth-ldap.conf Require valid-user - # TODO Restrict access to `newsfeed` group + # TODO Restrict access to `feed-reader` group diff --git a/plinth/modules/deluge/__init__.py b/plinth/modules/deluge/__init__.py index d73abc044..4144dee09 100644 --- a/plinth/modules/deluge/__init__.py +++ b/plinth/modules/deluge/__init__.py @@ -26,7 +26,7 @@ from plinth import action_utils from plinth import frontpage from plinth import service as service_module from plinth.menu import main_menu -from plinth.modules.users import add_group +from plinth.modules.users import create_group, register_group from .manifest import clients @@ -51,6 +51,8 @@ description = [ 'it immediately after enabling this service.') ] +group = ('bit-torrent', _('Download files using BitTorrent applications')) + reserved_usernames = ['debian-deluged'] clients = clients @@ -72,6 +74,7 @@ def init(): if is_enabled(): add_shortcut() + register_group(group) def setup(helper, old_version=None): @@ -86,7 +89,7 @@ def setup(helper, old_version=None): disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) - add_group('bittorrent') + create_group(group[0]) def add_shortcut(): diff --git a/plinth/modules/ikiwiki/__init__.py b/plinth/modules/ikiwiki/__init__.py index 6661deab0..14d920840 100644 --- a/plinth/modules/ikiwiki/__init__.py +++ b/plinth/modules/ikiwiki/__init__.py @@ -28,6 +28,7 @@ from plinth import cfg from plinth import frontpage from plinth import service as service_module from plinth.menu import main_menu +from plinth.modules.users import create_group, register_group from .manifest import clients @@ -61,6 +62,9 @@ description = [ clients = clients +group = ('wiki', _('View and edit wiki applications')) + + def init(): """Initialize the ikiwiki module.""" menu = main_menu.get('apps') @@ -75,6 +79,7 @@ def init(): if is_enabled(): add_shortcuts() + register_group(group) def setup(helper, old_version=None): @@ -88,6 +93,7 @@ def setup(helper, old_version=None): is_enabled=is_enabled, enable=enable, disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcuts) + create_group(group[0]) def add_shortcuts(): diff --git a/plinth/modules/transmission/__init__.py b/plinth/modules/transmission/__init__.py index 9a5b623d6..6af7da89e 100644 --- a/plinth/modules/transmission/__init__.py +++ b/plinth/modules/transmission/__init__.py @@ -25,7 +25,7 @@ from django.utils.translation import ugettext_lazy as _ from plinth import service as service_module from plinth import action_utils, actions, frontpage from plinth.menu import main_menu -from plinth.modules.users import add_group +from plinth.modules.users import create_group, register_group from .manifest import clients @@ -37,7 +37,7 @@ managed_packages = ['transmission-daemon'] name = _('Transmission') -short_description = _('BitTorrent') +short_description = _('BitTorrent Web Client') description = [ _('BitTorrent is a peer-to-peer file sharing protocol. ' @@ -50,6 +50,8 @@ clients = clients reserved_usernames = ['debian-transmission'] +group = ('bit-torrent', _('Download files using BitTorrent applications')) + service = None @@ -69,6 +71,7 @@ def init(): if is_enabled(): add_shortcut() + register_group(group) def setup(helper, old_version=None): @@ -92,7 +95,7 @@ def setup(helper, old_version=None): disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) - add_group('bit-torrent') + create_group(group[0]) def add_shortcut(): diff --git a/plinth/modules/ttrss/__init__.py b/plinth/modules/ttrss/__init__.py index bb1e90a20..aa4b4e7b6 100644 --- a/plinth/modules/ttrss/__init__.py +++ b/plinth/modules/ttrss/__init__.py @@ -28,7 +28,7 @@ from plinth import cfg from plinth import frontpage from plinth import service as service_module from plinth.menu import main_menu -from plinth.modules.users import add_group +from plinth.modules.users import create_group, register_group from .manifest import clients @@ -61,6 +61,8 @@ description = [ clients = clients +group = ('feed-reader', _('Read and subscribe to news feeds')) + service = None @@ -80,6 +82,7 @@ def init(): if is_enabled(): add_shortcut() + register_group(group) def setup(helper, old_version=None): @@ -95,7 +98,7 @@ def setup(helper, old_version=None): is_enabled=is_enabled, enable=enable, disable=disable) helper.call('post', service.notify_enabled, None, True) helper.call('post', add_shortcut) - add_group('newsfeed') + create_group(group[0]) def add_shortcut(): diff --git a/plinth/modules/users/__init__.py b/plinth/modules/users/__init__.py index 212b53786..2dc6a9d5b 100644 --- a/plinth/modules/users/__init__.py +++ b/plinth/modules/users/__init__.py @@ -45,6 +45,9 @@ first_boot_steps = [ name = _('Users and Groups') +# List of all Plinth user groups +groups = set() + def init(): """Intialize the user module.""" @@ -87,7 +90,7 @@ def _diagnose_ldap_entry(search_item): .format(search_item=search_item), result] -def add_group(group): +def create_group(group): """Add an LDAP group.""" actions.superuser_run('users', options=['create-group', group]) @@ -104,3 +107,7 @@ def get_all_groups(): return set(groups.strip().split()) except ActionError: return {} + + +def register_group(group): + groups.add(group) diff --git a/plinth/modules/users/forms.py b/plinth/modules/users/forms.py index e9dd953df..0925555b9 100644 --- a/plinth/modules/users/forms.py +++ b/plinth/modules/users/forms.py @@ -28,23 +28,18 @@ from django.utils.translation import ugettext as _, ugettext_lazy from plinth import actions from plinth.errors import ActionError from plinth.modules import first_boot +from plinth.modules import users from plinth.modules.security import set_restricted_access -from plinth.modules.users import get_all_groups from plinth.utils import is_user_admin from plinth import module_loader -PLINTH_APP_GROUPS = { - 'admin', - 'newsfeed', - } - def get_group_choices(): - groups = PLINTH_APP_GROUPS.intersection(get_all_groups()) - return ((group, _(group)) for group in groups) - - -GROUP_CHOICES = get_group_choices() + """Return localized group description and group name in one string.""" + admin_group = ('admin', _('Access to all services and system settings')) + users.register_group(admin_group) + choices = {(g[0], ('{} ({})'.format(g[1], g[0]))) for g in users.groups} + return sorted(list(choices), key=lambda g: g[0]) class ValidNewUsernameCheckMixin(object): @@ -84,10 +79,9 @@ class CreateUserForm(ValidNewUsernameCheckMixin, UserCreationForm): Include options to add user to groups. """ - groups = forms.MultipleChoiceField( - choices=GROUP_CHOICES, - label=ugettext_lazy('Groups'), + choices=get_group_choices(), + label=ugettext_lazy('Permissions'), required=False, widget=forms.CheckboxSelectMultiple, help_text=ugettext_lazy( @@ -103,6 +97,7 @@ class CreateUserForm(ValidNewUsernameCheckMixin, UserCreationForm): """Initialize the form with extra request argument.""" self.request = request super(CreateUserForm, self).__init__(*args, **kwargs) + self.fields['groups'].choices = get_group_choices() def save(self, commit=True): """Save the user model and create LDAP user if required.""" @@ -158,14 +153,21 @@ class UserUpdateForm(ValidNewUsernameCheckMixin, forms.ModelForm): def __init__(self, request, username, *args, **kwargs): """Initialize the form with extra request argument.""" - for group, group_name in GROUP_CHOICES: + group_choices = dict(get_group_choices()) + for group in group_choices: Group.objects.get_or_create(name=group) self.request = request self.username = username - super(UserUpdateForm, self).__init__(*args, **kwargs) + choices = [ # Replace group names with descriptions + (c[0], group_choices[c[1]]) + for c in sorted(self.fields['groups'].choices, key=lambda x: x[1])] + + self.fields['groups'].label = 'Permissions' + self.fields['groups'].choices = choices + if not is_user_admin(request): self.fields['is_active'].widget = forms.HiddenInput() self.fields['groups'].disabled = True @@ -278,7 +280,7 @@ class FirstBootForm(ValidNewUsernameCheckMixin, auth.forms.UserCreationForm): _('Failed to add new user to admin group.')) # Create initial Django groups - for group_choice in GROUP_CHOICES: + for group_choice in get_group_choices(): auth.models.Group.objects.get_or_create(name=group_choice[0]) admin_group = auth.models.Group.objects.get(name='admin')