diff --git a/openslides/agenda/apps.py b/openslides/agenda/apps.py index 5a1d22f3f..3a9b98c26 100644 --- a/openslides/agenda/apps.py +++ b/openslides/agenda/apps.py @@ -15,8 +15,10 @@ class AgendaAppConfig(AppConfig): from openslides.config.signals import config_signal from openslides.projector.api import register_slide from openslides.projector.signals import projector_overlays + from openslides.utils.rest_api import router from .signals import agenda_list_of_speakers, setup_agenda_config, listen_to_related_object_delete_signal from .slides import agenda_slide + from .views import ItemViewSet # Connect signals. config_signal.connect(setup_agenda_config, dispatch_uid='setup_agenda_config') @@ -26,3 +28,6 @@ class AgendaAppConfig(AppConfig): # Register slides. Item = self.get_model('Item') register_slide('agenda', agenda_slide, Item) + + # Register viewset. + router.register('agenda/item', ItemViewSet) diff --git a/openslides/agenda/serializers.py b/openslides/agenda/serializers.py new file mode 100644 index 000000000..576fc8781 --- /dev/null +++ b/openslides/agenda/serializers.py @@ -0,0 +1,34 @@ +from rest_framework import serializers + +from .models import Item, Speaker + + +class SpeakerSerializer(serializers.HyperlinkedModelSerializer): + """ + Serializer for a agenda.models.Speaker objects. + """ + class Meta: + model = Speaker + fields = ( + 'id', + 'user', + 'begin_time', + 'end_time', + 'weight') + + +class ItemSerializer(serializers.ModelSerializer): + """ + Serializer for a agenda.models.Item objects. + """ + get_title = serializers.CharField(read_only=True) + get_title_supplement = serializers.CharField(read_only=True) + item_no = serializers.CharField(read_only=True) + speaker_set = SpeakerSerializer(many=True, read_only=True) + # content_object = serializers.PrimaryKeyRelatedField(read_only=True) + + class Meta: + model = Item + exclude = ('content_type', 'object_id') + + # TODO: Problem: User can always see the time shedule. Filter fields with respect of permission. diff --git a/openslides/agenda/views.py b/openslides/agenda/views.py index 3de13950d..7780f50ac 100644 --- a/openslides/agenda/views.py +++ b/openslides/agenda/views.py @@ -23,6 +23,7 @@ from openslides.projector.api import ( get_projector_overlays_js, get_overlays, update_projector) +from openslides.utils import rest_api from openslides.utils.exceptions import OpenSlidesError from openslides.utils.pdf import stylesheet from openslides.utils.utils import html_strong @@ -42,6 +43,7 @@ from openslides.utils.views import ( from .csv_import import import_agenda_items from .forms import AppendSpeakerForm, ItemForm, ItemOrderForm, RelatedItemForm from .models import Item, Speaker +from .serializers import ItemSerializer class Overview(TemplateView): @@ -773,3 +775,42 @@ class ItemCSVImportView(CSVImportView): required_permission = 'agenda.can_manage_agenda' success_url_name = 'item_overview' template_name = 'agenda/item_form_csv_import.html' + + +class ItemViewSet(rest_api.viewsets.ModelViewSet): + """ + API endpoint to view, edit and delete agenda items. + """ + model = Item + serializer_class = ItemSerializer + + def check_permissions(self, request): + """ + Calls self.permission_denied() if the requesting user has not the + permission to see and in case of create, update or destroy requests + the permission to manage. + """ + if not request.user.has_perm('agenda.can_see_agenda'): + self.permission_denied(request) + elif (self.action in ('create', 'update', 'destroy') + and not request.user.has_perm('agenda.can_manage_agenda')): + # This is the same as self.action not in ('list', 'retrieve') + self.permission_denied(request) + + def check_object_permissions(self, request, obj): + """ + Checks if the requesting user has permission to see also an + organizational item if it is one. + """ + if obj.type == obj.ORGANIZATIONAL_ITEM and not request.user.has_perm('agenda.can_see_orga_items'): + self.permission_denied(request) + + def get_queryset(self): + """ + Filters organizational items if the user has no permission to see it. + """ + queryset = Item.objects.all() + if (not self.request.user.has_perm('agenda.can_see_orga_items') and + not self.request.user.has_perm('agenda.can_manage_agenda')): + queryset = queryset.exclude(type__exact=Item.ORGANIZATIONAL_ITEM) + return queryset diff --git a/openslides/utils/rest_api.py b/openslides/utils/rest_api.py index 5fec051f5..8fc21f00e 100644 --- a/openslides/utils/rest_api.py +++ b/openslides/utils/rest_api.py @@ -1,3 +1,3 @@ -from rest_framework import permissions, routers, viewsets +from rest_framework import permissions, routers, viewsets # noqa router = routers.DefaultRouter()