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')