diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e6ee11f3d..51b632f0d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -24,6 +24,9 @@ Core: Motions: - Option to customly sort motions [#3894]. - Added support for adding a statute [#3894]. + - Added new permission to manage metadata, i. e. set motion state, set and + follow recommendation, manage submitters and supporters, change motion + category, motion block and origin and manage motion polls [#3913]. User: - Added new admin group which grants all permissions. Users of existing group diff --git a/openslides/motions/migrations/0015_metadata_permission.py b/openslides/motions/migrations/0015_metadata_permission.py new file mode 100644 index 000000000..fc583971f --- /dev/null +++ b/openslides/motions/migrations/0015_metadata_permission.py @@ -0,0 +1,28 @@ +# Generated by Django 2.1.2 on 2018-10-29 13:54 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('motions', '0014_motionchangerecommendation_internal'), + ] + + operations = [ + migrations.AlterModelOptions( + name='motion', + options={ + 'default_permissions': (), + 'ordering': ('identifier',), + 'permissions': ( + ('can_see', 'Can see motions'), + ('can_create', 'Can create motions'), + ('can_support', 'Can support motions'), + ('can_manage_metadata', 'Can manage motion metadata'), + ('can_manage', 'Can manage motions') + ), + 'verbose_name': 'Motion' + }, + ), + ] diff --git a/openslides/motions/models.py b/openslides/motions/models.py index c6098dd16..e814c7efa 100644 --- a/openslides/motions/models.py +++ b/openslides/motions/models.py @@ -250,6 +250,7 @@ class Motion(RESTModelMixin, models.Model): ('can_see', 'Can see motions'), ('can_create', 'Can create motions'), ('can_support', 'Can support motions'), + ('can_manage_metadata', 'Can manage motion metadata'), ('can_manage', 'Can manage motions'), ) ordering = ('identifier', ) diff --git a/openslides/motions/views.py b/openslides/motions/views.py index c387f74e5..4596070ad 100644 --- a/openslides/motions/views.py +++ b/openslides/motions/views.py @@ -73,16 +73,19 @@ class MotionViewSet(ModelViewSet): result = self.get_access_permissions().check_permissions(self.request.user) elif self.action in ('metadata', 'partial_update', 'update', 'destroy'): result = has_perm(self.request.user, 'motions.can_see') - # For partial_update, update and delete requests the rest of the check is + # For partial_update, update and destroy requests the rest of the check is # done in the update method. See below. elif self.action == 'create': result = (has_perm(self.request.user, 'motions.can_see') and has_perm(self.request.user, 'motions.can_create') and (not config['motions_stop_submitting'] or has_perm(self.request.user, 'motions.can_manage'))) - elif self.action in ('set_state', 'sort', 'manage_comments', 'set_recommendation', - 'follow_recommendation', 'create_poll', 'manage_submitters', - 'sort_submitters'): + elif self.action in ('set_state', 'set_recommendation', + 'follow_recommendation', 'manage_submitters', + 'sort_submitters', 'create_poll'): + result = (has_perm(self.request.user, 'motions.can_see') and + has_perm(self.request.user, 'motions.can_manage_metadata')) + elif self.action in ('sort', 'manage_comments'): result = (has_perm(self.request.user, 'motions.can_see') and has_perm(self.request.user, 'motions.can_manage')) elif self.action == 'support': @@ -147,6 +150,8 @@ class MotionViewSet(ModelViewSet): del request.data[key] # Validate data and create motion. + # Attention: Even user without permission can_manage_metadata is allowed + # to create a new motion and set such metadata like category, motion block and origin. serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) motion = serializer.save(request_user=request.user) @@ -218,10 +223,14 @@ class MotionViewSet(ModelViewSet): # Check permissions. if (not has_perm(request.user, 'motions.can_manage') and + not has_perm(request.user, 'motions.can_manage_metadata') and not (motion.is_submitter(request.user) and motion.state.allow_submitter_edit)): self.permission_denied(request) # Check permission to send only some data. + # Attention: Users with motions.can_manage permission can change all + # fields even if they do not have motions.can_manage_metadata + # permission. if not has_perm(request.user, 'motions.can_manage'): # Remove fields that the user is not allowed to change. # The list() is required because we want to use del inside the loop. @@ -234,6 +243,15 @@ class MotionViewSet(ModelViewSet): 'text', 'reason', )) + + if has_perm(request.user, 'motions.can_manage_metadata'): + whitelist.extend(( + 'category_id', + 'motion_block_id', + 'origin', + 'supporters_id', + )) + for key in keys: if key not in whitelist: del request.data[key] @@ -298,10 +316,12 @@ class MotionViewSet(ModelViewSet): def manage_comments(self, request, pk=None): """ Create, update and delete motion comments. - Send a post request with {'section_id': , 'comment': ''} to create - a new comment or update an existing comment. - Send a delete request with just {'section_id': } to delete the comment. - For ever request, the user must have read and write permission for the given field. + + Send a POST request with {'section_id': , 'comment': ''} + to create a new comment or update an existing comment. + + Send a DELETE request with just {'section_id': } to delete the comment. + For every request, the user must have read and write permission for the given field. """ motion = self.get_object() @@ -634,7 +654,7 @@ class MotionPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet): Returns True if the user has required permissions. """ return (has_perm(self.request.user, 'motions.can_see') and - has_perm(self.request.user, 'motions.can_manage')) + has_perm(self.request.user, 'motions.can_manage_metadata')) def update(self, *args, **kwargs): """ diff --git a/openslides/users/signals.py b/openslides/users/signals.py index ac762f391..e7d021a3e 100644 --- a/openslides/users/signals.py +++ b/openslides/users/signals.py @@ -53,6 +53,7 @@ def create_builtin_groups_and_admin(**kwargs): 'mediafiles.can_upload', 'motions.can_create', 'motions.can_manage', + 'motions.can_manage_metadata', 'motions.can_see', 'motions.can_support', 'users.can_manage', @@ -126,6 +127,7 @@ def create_builtin_groups_and_admin(**kwargs): permission_dict['motions.can_see'], permission_dict['motions.can_create'], permission_dict['motions.can_manage'], + permission_dict['motions.can_manage_metadata'], permission_dict['users.can_see_name'], permission_dict['users.can_manage'], permission_dict['users.can_see_extra_data'],