From 965206e1fc333243d755aa693fd6e12c014d33f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Mon, 31 Aug 2015 14:07:24 +0200 Subject: [PATCH] Set permissions for OPTIONS requests. Fixed js-data dependency. Fixed blank in some motion model fields. Fixed error handling in agenda and core views. --- bower.json | 1 + openslides/agenda/views.py | 8 ++--- openslides/assignments/views.py | 8 ++--- openslides/core/views.py | 27 ++++++++-------- openslides/mediafiles/views.py | 6 ++-- .../migrations/0002_auto_20150904_1448.py | 32 +++++++++++++++++++ openslides/motions/models.py | 8 ++--- openslides/motions/views.py | 18 +++++------ openslides/users/views.py | 16 +++++----- requirements_production.txt | 2 +- 10 files changed, 80 insertions(+), 46 deletions(-) create mode 100644 openslides/motions/migrations/0002_auto_20150904_1448.py diff --git a/bower.json b/bower.json index 796dad8bc..8439bd0c9 100644 --- a/bower.json +++ b/bower.json @@ -18,6 +18,7 @@ "angular-gettext": "~2.0.2", "angular-sanitize": "~1.3.15", "angular-xeditable": "~0.1.9", + "js-data": "~1.8.0", "js-data-angular": "~2.1.0", "ng-fab-form": "~1.2.7", "ngBootbox": "~0.0.5", diff --git a/openslides/agenda/views.py b/openslides/agenda/views.py index 1d20ee74a..532c651e5 100644 --- a/openslides/agenda/views.py +++ b/openslides/agenda/views.py @@ -26,8 +26,8 @@ class ItemViewSet(ModelViewSet): """ API endpoint for agenda items. - There are the following views: list, retrieve, create, partial_update, - update, destroy, manage_speaker, speak and tree. + There are the following views: metadata, list, retrieve, create, + partial_update, update, destroy, manage_speaker, speak and tree. """ queryset = Item.objects.all() serializer_class = ItemSerializer @@ -36,7 +36,7 @@ class ItemViewSet(ModelViewSet): """ Returns True if the user has required permissions. """ - if self.action in ('list', 'retrieve', 'manage_speaker', 'tree'): + if self.action in ('metadata', 'list', 'retrieve', 'manage_speaker', 'tree'): result = self.request.user.has_perm('agenda.can_see') # For manage_speaker and tree requests the rest of the check is # done in the specific method. See below. @@ -113,7 +113,7 @@ class ItemViewSet(ModelViewSet): try: Speaker.objects.add(user, item) except OpenSlidesError as e: - raise ValidationError({'detail': e}) + raise ValidationError({'detail': str(e)}) message = _('User %s was successfully added to the list of speakers.') % user else: diff --git a/openslides/assignments/views.py b/openslides/assignments/views.py index 4199d5a16..e5c2b045d 100644 --- a/openslides/assignments/views.py +++ b/openslides/assignments/views.py @@ -43,9 +43,9 @@ class AssignmentViewSet(ModelViewSet): """ API endpoint for assignments. - There are the following views: list, retrieve, create, partial_update, - update, destroy, candidature_self, candidature_other, mark_elected and - create_poll. + There are the following views: metadata, list, retrieve, create, + partial_update, update, destroy, candidature_self, candidature_other, + mark_elected and create_poll. """ queryset = Assignment.objects.all() @@ -53,7 +53,7 @@ class AssignmentViewSet(ModelViewSet): """ Returns True if the user has required permissions. """ - if self.action in ('list', 'retrieve'): + if self.action in ('metadata', 'list', 'retrieve'): result = self.request.user.has_perm('assignments.can_see') elif self.action in ('create', 'partial_update', 'update', 'destroy', 'mark_elected', 'create_poll'): diff --git a/openslides/core/views.py b/openslides/core/views.py index 076883f1c..48e2b0211 100644 --- a/openslides/core/views.py +++ b/openslides/core/views.py @@ -99,7 +99,7 @@ class AppsJsView(utils_views.View): "angular.module('OpenSlidesApp.{app}', {angular_modules});" "var deferres = [];" "{js_files}.forEach(function(js_file)deferres.push($.getScript(js_file)));" - "$.when.apply(this, deferres).done(function() angular.bootstrap(document,['OpenSlidesApp.{app}']));" + "$.when.apply(this, deferres).done(function()angular.bootstrap(document,['OpenSlidesApp.{app}']));" .format( app=kwargs.get('openslides_app'), angular_modules=angular_modules, @@ -218,8 +218,8 @@ class CustomSlideViewSet(ModelViewSet): """ API endpoint for custom slides. - There are the following views: list, retrieve, create, partial_update, - update and destroy. + There are the following views: metadata, list, retrieve, create, + partial_update, update and destroy. """ queryset = CustomSlide.objects.all() serializer_class = CustomSlideSerializer @@ -235,8 +235,8 @@ class TagViewSet(ModelViewSet): """ API endpoint for tags. - There are the following views: list, retrieve, create, partial_update, - update and destroy. + There are the following views: metadata, list, retrieve, create, + partial_update, update and destroy. """ queryset = Tag.objects.all() serializer_class = TagSerializer @@ -245,9 +245,9 @@ class TagViewSet(ModelViewSet): """ Returns True if the user has required permissions. """ - if self.action in ('list', 'retrieve'): - # Every authenticated user can list or retrieve tags. - # Anonymous users can do so if they are enabled. + if self.action in ('metadata', 'list', 'retrieve'): + # Every authenticated user can see the metadata and list or + # retrieve tags. Anonymous users can do so if they are enabled. result = self.request.user.is_authenticated() or config['general_system_enable_anonymous'] elif self.action in ('create', 'update', 'destroy'): result = self.request.user.has_perm('core.can_manage_tags') @@ -287,7 +287,7 @@ class ConfigViewSet(ViewSet): """ API endpoint for the config. - There are the following views: list, retrieve and update. + There are the following views: metadata, list, retrieve and update. """ metadata_class = ConfigMetadata @@ -295,9 +295,10 @@ class ConfigViewSet(ViewSet): """ Returns True if the user has required permissions. """ - if self.action in ('list', 'retrieve'): - # Every authenticated user can list or retrieve the config. - # Anonymous users can do so if they are enabled. + if self.action in ('metadata', 'list', 'retrieve'): + # Every authenticated user can see the metadata and list or + # retrieve the config. Anonymous users can do so if they are + # enabled. result = self.request.user.is_authenticated() or config['general_system_enable_anonymous'] elif self.action == 'update': result = self.request.user.has_perm('core.can_manage_config') @@ -337,7 +338,7 @@ class ConfigViewSet(ViewSet): except ConfigNotFound: raise Http404 except ConfigError as e: - raise ValidationError({'detail': e}) + raise ValidationError({'detail': str(e)}) # Return response. return Response({'key': key, 'value': value}) diff --git a/openslides/mediafiles/views.py b/openslides/mediafiles/views.py index bad984d07..d63a3dcb2 100644 --- a/openslides/mediafiles/views.py +++ b/openslides/mediafiles/views.py @@ -10,8 +10,8 @@ class MediafileViewSet(ModelViewSet): """ API endpoint for mediafile objects. - There are the following views: list, retrieve, create, partial_update, - update and destroy. + There are the following views: metadata, list, retrieve, create, + partial_update, update and destroy. """ queryset = Mediafile.objects.all() serializer_class = MediafileSerializer @@ -22,7 +22,7 @@ class MediafileViewSet(ModelViewSet): """ # TODO: Use mediafiles.can_upload permission to create and update some # objects but restricted concerning the uploader. - if self.action in ('list', 'retrieve'): + if self.action in ('metadata', 'list', 'retrieve'): result = self.request.user.has_perm('mediafiles.can_see') elif self.action in ('create', 'partial_update', 'update'): result = (self.request.user.has_perm('mediafiles.can_see') and diff --git a/openslides/motions/migrations/0002_auto_20150904_1448.py b/openslides/motions/migrations/0002_auto_20150904_1448.py new file mode 100644 index 000000000..9f451f43e --- /dev/null +++ b/openslides/motions/migrations/0002_auto_20150904_1448.py @@ -0,0 +1,32 @@ +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('motions', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='motion', + name='attachments', + field=models.ManyToManyField(blank=True, to='mediafiles.Mediafile'), + ), + migrations.AlterField( + model_name='motion', + name='submitters', + field=models.ManyToManyField(blank=True, related_name='motion_submitters', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='motion', + name='supporters', + field=models.ManyToManyField(blank=True, related_name='motion_supporters', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='motion', + name='tags', + field=models.ManyToManyField(blank=True, to='core.Tag'), + ), + ] diff --git a/openslides/motions/models.py b/openslides/motions/models.py index 79201c50a..3992832cf 100644 --- a/openslides/motions/models.py +++ b/openslides/motions/models.py @@ -69,7 +69,7 @@ class Motion(RESTModelMixin, models.Model): ForeignKey to one category of motions. """ - attachments = models.ManyToManyField(Mediafile) + attachments = models.ManyToManyField(Mediafile, blank=True) """ Many to many relation to mediafile objects. """ @@ -81,17 +81,17 @@ class Motion(RESTModelMixin, models.Model): Null if the motion is not an amendment. """ - tags = models.ManyToManyField(Tag) + tags = models.ManyToManyField(Tag, blank=True) """ Tags to categorise motions. """ - submitters = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='motion_submitters') + submitters = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='motion_submitters', blank=True) """ Users who submit this motion. """ - supporters = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='motion_supporters') + supporters = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='motion_supporters', blank=True) """ Users who support this motion. """ diff --git a/openslides/motions/views.py b/openslides/motions/views.py index f0483327c..26c3bd5cd 100644 --- a/openslides/motions/views.py +++ b/openslides/motions/views.py @@ -30,8 +30,8 @@ class MotionViewSet(ModelViewSet): """ API endpoint for motions. - There are the following views: list, retrieve, create, partial_update, - update, destroy, manage_version, support and set_state. + There are the following views: metadata, list, retrieve, create, + partial_update, update, destroy, manage_version, support and set_state. """ queryset = Motion.objects.all() serializer_class = MotionSerializer @@ -40,7 +40,7 @@ class MotionViewSet(ModelViewSet): """ Returns True if the user has required permissions. """ - if self.action in ('list', 'retrieve', 'partial_update', 'update'): + if self.action in ('metadata', 'list', 'retrieve', 'partial_update', 'update'): result = self.request.user.has_perm('motions.can_see') # For partial_update and update requests the rest of the check is # done in the update method. See below. @@ -236,8 +236,8 @@ class CategoryViewSet(ModelViewSet): """ API endpoint for categories. - There are the following views: list, retrieve, create, partial_update, - update and destroy. + There are the following views: metadata, list, retrieve, create, + partial_update, update and destroy. """ queryset = Category.objects.all() serializer_class = CategorySerializer @@ -246,7 +246,7 @@ class CategoryViewSet(ModelViewSet): """ Returns True if the user has required permissions. """ - if self.action in ('list', 'retrieve'): + if self.action in ('metadata', 'list', 'retrieve'): result = self.request.user.has_perm('motions.can_see') elif self.action in ('create', 'partial_update', 'update', 'destroy'): result = (self.request.user.has_perm('motions.can_see') and @@ -260,8 +260,8 @@ class WorkflowViewSet(ModelViewSet): """ API endpoint for workflows. - There are the following views: list, retrieve, create, partial_update, - update and destroy. + There are the following views: metadata, list, retrieve, create, + partial_update, update and destroy. """ queryset = Workflow.objects.all() serializer_class = WorkflowSerializer @@ -270,7 +270,7 @@ class WorkflowViewSet(ModelViewSet): """ Returns True if the user has required permissions. """ - if self.action in ('list', 'retrieve'): + if self.action in ('metadata', 'list', 'retrieve'): result = self.request.user.has_perm('motions.can_see') elif self.action in ('create', 'partial_update', 'update', 'destroy'): result = (self.request.user.has_perm('motions.can_see') and diff --git a/openslides/users/views.py b/openslides/users/views.py index 3bdd78a0a..30b1dde26 100644 --- a/openslides/users/views.py +++ b/openslides/users/views.py @@ -24,8 +24,8 @@ class UserViewSet(ModelViewSet): """ API endpoint for users. - There are the following views: list, retrieve, create, partial_update, - update, destroy and reset_password. + There are the following views: metadata, list, retrieve, create, + partial_update, update, destroy and reset_password. """ queryset = User.objects.all() @@ -33,7 +33,7 @@ class UserViewSet(ModelViewSet): """ Returns True if the user has required permissions. """ - if self.action in ('list', 'retrieve'): + if self.action in ('metadata', 'list', 'retrieve'): result = self.request.user.has_perm('users.can_see_name') elif self.action in ('create', 'partial_update', 'update', 'destroy', 'reset_password'): result = (self.request.user.has_perm('users.can_see_name') and @@ -72,8 +72,8 @@ class GroupViewSet(ModelViewSet): """ API endpoint for groups. - There are the following views: list, retrieve, create, partial_update, - update and destroy. + There are the following views: metadata, list, retrieve, create, + partial_update, update and destroy. """ queryset = Group.objects.all() serializer_class = GroupSerializer @@ -82,9 +82,9 @@ class GroupViewSet(ModelViewSet): """ Returns True if the user has required permissions. """ - if self.action in ('list', 'retrieve'): - # Every authenticated user can list or retrieve groups. - # Anonymous users can do so if they are enabled. + if self.action in ('metadata', 'list', 'retrieve'): + # Every authenticated user can see the metadata and list or + # retrieve groups. Anonymous users can do so if they are enabled. result = self.request.user.is_authenticated() or config['general_system_enable_anonymous'] elif self.action in ('create', 'partial_update', 'update', 'destroy'): # Users with all app permissions can edit groups. diff --git a/requirements_production.txt b/requirements_production.txt index b8539344e..0306c6e3a 100644 --- a/requirements_production.txt +++ b/requirements_production.txt @@ -3,7 +3,7 @@ Django>=1.7.1,<1.9 beautifulsoup4>=4.1,<4.4 bleach>=1.4,<1.5 django-haystack>=2.1,<2.5 -djangorestframework>=3.0.5,<3.2.0 +djangorestframework>=3.2.0,<3.3.0 jsonfield>=0.9.19,<1.1 natsort>=3.2,<4.1 reportlab>=3.0,<3.3