Merge pull request #3366 from FinnStutzenstein/Issue3363

New permission for managing lists of speakers (fixes #3363)
This commit is contained in:
Emanuel Schütze 2017-09-08 22:05:32 +02:00 committed by GitHub
commit 3a25e87330
8 changed files with 51 additions and 19 deletions

View File

@ -11,6 +11,7 @@ Version 2.2 (unreleased)
Agenda: Agenda:
- Fixed wrong sorting of last speakers [#3193]. - Fixed wrong sorting of last speakers [#3193].
- Fixed issue when sorting a new inserted speaker [#3210]. - Fixed issue when sorting a new inserted speaker [#3210].
- New permission for managing lists of speakers [#3366].
Motions: Motions:
- New export dialog [#3185]. - New export dialog [#3185].

View File

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-08-18 10:02
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('agenda', '0002_item_duration'),
]
operations = [
migrations.AlterModelOptions(
name='item',
options={
'default_permissions': (),
'permissions': (
('can_see', 'Can see agenda'),
('can_manage', 'Can manage agenda'),
('can_manage_list_of_speakers', 'Can manage list of speakers'),
('can_see_hidden_items', 'Can see hidden items and time scheduling of agenda')
)
},
),
]

View File

@ -279,6 +279,7 @@ class Item(RESTModelMixin, models.Model):
permissions = ( permissions = (
('can_see', 'Can see agenda'), ('can_see', 'Can see agenda'),
('can_manage', 'Can manage agenda'), ('can_manage', 'Can manage agenda'),
('can_manage_list_of_speakers', 'Can manage list of speakers'),
('can_see_hidden_items', 'Can see hidden items and time scheduling of agenda')) ('can_see_hidden_items', 'Can see hidden items and time scheduling of agenda'))
unique_together = ('content_type', 'object_id') unique_together = ('content_type', 'object_id')

View File

@ -451,7 +451,6 @@ angular.module('OpenSlidesApp.agenda.site', [
$http.post('/rest/agenda/item/' + $scope.item.id + '/manage_speaker/', {'user': userId}).then( $http.post('/rest/agenda/item/' + $scope.item.id + '/manage_speaker/', {'user': userId}).then(
function (success) { function (success) {
$scope.alert.show = false; $scope.alert.show = false;
$scope.speakers = $scope.item.speakers;
$scope.speakerSelectBox = {}; $scope.speakerSelectBox = {};
}, function (error) { }, function (error) {
$scope.alert = ErrorMessage.forAlert(error); $scope.alert = ErrorMessage.forAlert(error);
@ -468,11 +467,9 @@ angular.module('OpenSlidesApp.agenda.site', [
data: JSON.stringify({speaker: speakerId})} data: JSON.stringify({speaker: speakerId})}
) )
.then(function (success) { .then(function (success) {
$scope.speakers = $scope.item.speakers;
}, function (error) { }, function (error) {
$scope.alert = ErrorMessage.forAlert(error); $scope.alert = ErrorMessage.forAlert(error);
}); });
$scope.speakers = $scope.item.speakers;
}; };
//delete all speakers from list of speakers //delete all speakers from list of speakers
@ -487,11 +484,9 @@ angular.module('OpenSlidesApp.agenda.site', [
data: JSON.stringify({speaker: speakersOnList})} data: JSON.stringify({speaker: speakersOnList})}
) )
.then(function (success) { .then(function (success) {
$scope.speakers = $scope.item.speakers;
}, function (error) { }, function (error) {
$scope.alert = ErrorMessage.forAlert(error); $scope.alert = ErrorMessage.forAlert(error);
}); });
$scope.speakers = $scope.item.speakers;
}; };
// Return true if the requested user is allowed to do a specific action // Return true if the requested user is allowed to do a specific action
@ -512,13 +507,13 @@ angular.module('OpenSlidesApp.agenda.site', [
} }
return false; return false;
case 'removeAll': case 'removeAll':
return (operator.hasPerms('agenda.can_manage') && return (operator.hasPerms('agenda.can_manage_list_of_speakers') &&
$scope.speakers.length > 0); $scope.speakers.length > 0);
case 'beginNextSpeech': case 'beginNextSpeech':
return (operator.hasPerms('agenda.can_manage') && return (operator.hasPerms('agenda.can_manage_list_of_speakers') &&
$scope.nextSpeakers.length > 0); $scope.nextSpeakers.length > 0);
case 'endCurrentSpeech': case 'endCurrentSpeech':
return (operator.hasPerms('agenda.can_manage') && return (operator.hasPerms('agenda.can_manage_list_of_speakers') &&
$scope.currentSpeaker.length > 0); $scope.currentSpeaker.length > 0);
case 'showLastSpeakers': case 'showLastSpeakers':
return $scope.lastSpeakers.length > 0; return $scope.lastSpeakers.length > 0;

View File

@ -1,13 +1,15 @@
<div ng-if="item" class="details" ng-controller="ListOfSpeakersManagementCtrl"> <div ng-if="item" class="details" ng-controller="ListOfSpeakersManagementCtrl">
<div class="speakers-toolbar"> <div class="speakers-toolbar">
<div class="pull-right"> <div class="pull-right">
<span os-perms="agenda.can_manage"> <span os-perms="agenda.can_manage_list_of_speakers">
<button ng-if="isAllowed('removeAll')" class="btn btn-sm btn-danger" <button ng-if="isAllowed('removeAll')" class="btn btn-sm btn-danger"
ng-bootbox-confirm="{{ 'Are you sure you want to remove all speakers from this list?'| translate }}" ng-bootbox-confirm="{{ 'Are you sure you want to remove all speakers from this list?'| translate }}"
ng-bootbox-confirm-action="removeAllSpeakers()"> ng-bootbox-confirm-action="removeAllSpeakers()">
<i class="fa fa-trash fa-lg"></i> <i class="fa fa-trash fa-lg"></i>
<translate>Remove all speakers</translate> <translate>Remove all speakers</translate>
</button> </button>
</span>
<span os-perms="agenda.can_manage">
<button ng-if="item.speaker_list_closed" ng-click="closeList(false)" <button ng-if="item.speaker_list_closed" ng-click="closeList(false)"
class="btn btn-sm btn-default"> class="btn btn-sm btn-default">
<i class="fa fa-toggle-off"></i> <i class="fa fa-toggle-off"></i>
@ -57,7 +59,7 @@
(<translate>Start time</translate>: (<translate>Start time</translate>:
{{ speaker.begin_time | date:'yyyy-MM-dd HH:mm:ss' }}) {{ speaker.begin_time | date:'yyyy-MM-dd HH:mm:ss' }})
</small> </small>
<button os-perms="agenda.can_manage" ng-click="removeSpeaker(speaker.id)" <button os-perms="agenda.can_manage_list_of_speakers" ng-click="removeSpeaker(speaker.id)"
class="btn btn-default btn-xs" title="{{ 'Remove' | translate }}"> class="btn btn-default btn-xs" title="{{ 'Remove' | translate }}">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</button> </button>
@ -69,11 +71,11 @@
<p ng-repeat="speaker in currentSpeaker" class="currentSpeaker spacer indentation"> <p ng-repeat="speaker in currentSpeaker" class="currentSpeaker spacer indentation">
<i class="fa fa-microphone fa-lg"></i> <i class="fa fa-microphone fa-lg"></i>
{{ speaker.user.get_full_name() }} {{ speaker.user.get_full_name() }}
<button os-perms="agenda.can_manage" ng-click="endSpeech()" <button os-perms="agenda.can_manage_list_of_speakers" ng-click="endSpeech()"
class="btn btn-default btn-sm" title="{{ 'End speech' | translate }}"> class="btn btn-default btn-sm" title="{{ 'End speech' | translate }}">
<i class="fa fa-microphone-slash"></i> <translate>Stop</translate> <i class="fa fa-microphone-slash"></i> <translate>Stop</translate>
</button> </button>
<button os-perms="agenda.can_manage" ng-click="removeSpeaker(speaker.id)" <button os-perms="agenda.can_manage_list_of_speakers" ng-click="removeSpeaker(speaker.id)"
class="btn btn-default btn-sm" title="{{ 'Remove' | translate }}"> class="btn btn-default btn-sm" title="{{ 'Remove' | translate }}">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</button> </button>
@ -84,15 +86,15 @@
<div ui-tree="treeOptions" data-empty-placeholder-enabled="false"> <div ui-tree="treeOptions" data-empty-placeholder-enabled="false">
<ol ui-tree-nodes="" ng-model="nextSpeakers"> <ol ui-tree-nodes="" ng-model="nextSpeakers">
<li ng-repeat="speaker in nextSpeakers | orderBy:'weight'" ui-tree-node> <li ng-repeat="speaker in nextSpeakers | orderBy:'weight'" ui-tree-node>
<i os-perms="agenda.can_manage" ui-tree-handle="" class="fa fa-arrows-v"></i> <i os-perms="agenda.can_manage_list_of_speakers" ui-tree-handle="" class="fa fa-arrows-v"></i>
{{ $index + 1 }}. {{ $index + 1 }}.
{{ speaker.user.get_full_name() }} {{ speaker.user.get_full_name() }}
&nbsp; &nbsp;
<button os-perms="agenda.can_manage" ng-click="beginSpeech(speaker.id)" <button os-perms="agenda.can_manage_list_of_speakers" ng-click="beginSpeech(speaker.id)"
class="btn btn-default btn-sm" title="{{ 'Begin speech' | translate }}"> class="btn btn-default btn-sm" title="{{ 'Begin speech' | translate }}">
<i class="fa fa-microphone"></i> <translate>Start</translate> <i class="fa fa-microphone"></i> <translate>Start</translate>
</button> </button>
<button os-perms="agenda.can_manage" ng-click="removeSpeaker(speaker.id)" <button os-perms="agenda.can_manage_list_of_speakers" ng-click="removeSpeaker(speaker.id)"
class="btn btn-default btn-sm" title="{{ 'Remove' | translate }}"> class="btn btn-default btn-sm" title="{{ 'Remove' | translate }}">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</button> </button>
@ -105,7 +107,7 @@
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" ng-click="alert={}" close="alert={}"> <div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" ng-click="alert={}" close="alert={}">
{{ alert.msg }} {{ alert.msg }}
</div> </div>
<div os-perms="agenda.can_manage"> <div os-perms="agenda.can_manage_list_of_speakers">
<select chosen <select chosen
ng-model="speakerSelectBox.selected" ng-model="speakerSelectBox.selected"
ng-change="addSpeaker(speakerSelectBox.selected)" ng-change="addSpeaker(speakerSelectBox.selected)"

View File

@ -47,7 +47,10 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
result = (has_perm(self.request.user, 'agenda.can_see') and result = (has_perm(self.request.user, 'agenda.can_see') and
has_perm(self.request.user, 'agenda.can_see_hidden_items') and has_perm(self.request.user, 'agenda.can_see_hidden_items') and
has_perm(self.request.user, 'agenda.can_manage')) has_perm(self.request.user, 'agenda.can_manage'))
elif self.action in ('speak', 'sort_speakers', 'numbering', 'sort'): elif self.action in ('speak', 'sort_speakers'):
result = (has_perm(self.request.user, 'agenda.can_see') and
has_perm(self.request.user, 'agenda.can_manage_list_of_speakers'))
elif self.action in ('numbering', 'sort'):
result = (has_perm(self.request.user, 'agenda.can_see') and result = (has_perm(self.request.user, 'agenda.can_see') and
has_perm(self.request.user, 'agenda.can_manage')) has_perm(self.request.user, 'agenda.can_manage'))
else: else:
@ -88,7 +91,7 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
user = self.request.user user = self.request.user
else: else:
# Add someone else. # Add someone else.
if not has_perm(self.request.user, 'agenda.can_manage'): if not has_perm(self.request.user, 'agenda.can_manage_list_of_speakers'):
self.permission_denied(request) self.permission_denied(request)
try: try:
user = get_user_model().objects.get(pk=int(user_id)) user = get_user_model().objects.get(pk=int(user_id))
@ -128,7 +131,7 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
message = _('You are successfully removed from the list of speakers.') message = _('You are successfully removed from the list of speakers.')
else: else:
# Remove someone else. # Remove someone else.
if not has_perm(self.request.user, 'agenda.can_manage'): if not has_perm(self.request.user, 'agenda.can_manage_list_of_speakers'):
self.permission_denied(request) self.permission_denied(request)
if type(speaker_ids) is int: if type(speaker_ids) is int:
speaker_ids = [speaker_ids] speaker_ids = [speaker_ids]

View File

@ -31,6 +31,7 @@ def create_builtin_groups_and_admin(**kwargs):
permission_strings = ( permission_strings = (
'agenda.can_be_speaker', 'agenda.can_be_speaker',
'agenda.can_manage', 'agenda.can_manage',
'agenda.can_manage_list_of_speakers',
'agenda.can_see', 'agenda.can_see',
'agenda.can_see_hidden_items', 'agenda.can_see_hidden_items',
'assignments.can_manage', 'assignments.can_manage',
@ -107,6 +108,7 @@ def create_builtin_groups_and_admin(**kwargs):
permission_dict['agenda.can_see_hidden_items'], permission_dict['agenda.can_see_hidden_items'],
permission_dict['agenda.can_be_speaker'], permission_dict['agenda.can_be_speaker'],
permission_dict['agenda.can_manage'], permission_dict['agenda.can_manage'],
permission_dict['agenda.can_manage_list_of_speakers'],
permission_dict['assignments.can_see'], permission_dict['assignments.can_see'],
permission_dict['assignments.can_manage'], permission_dict['assignments.can_manage'],
permission_dict['assignments.can_nominate_other'], permission_dict['assignments.can_nominate_other'],

View File

@ -1596,6 +1596,7 @@ angular.module('OpenSlidesApp.users.site', [
// agenda // agenda
gettext('Can see agenda'); gettext('Can see agenda');
gettext('Can manage agenda'); gettext('Can manage agenda');
gettext('Can manage list of speakers');
gettext('Can see hidden items and time scheduling of agenda'); gettext('Can see hidden items and time scheduling of agenda');
gettext('Can put oneself on the list of speakers'); gettext('Can put oneself on the list of speakers');
// assignments // assignments