diff options
| author | Tom Christie | 2013-02-10 16:50:46 +0000 | 
|---|---|---|
| committer | Tom Christie | 2013-02-10 16:50:46 +0000 | 
| commit | 29136ef2c6338b8dbc9f7cf9c4dd75867a6bfa9f (patch) | |
| tree | 97af2eecca3681d344a8a1ec82a85f43611df1b3 /rest_framework | |
| parent | 84a1896b7de5c2e3fc5f564027e5fccd7b2447f9 (diff) | |
| download | django-rest-framework-29136ef2c6338b8dbc9f7cf9c4dd75867a6bfa9f.tar.bz2 | |
Enforce PUT-as-create permissions
Diffstat (limited to 'rest_framework')
| -rw-r--r-- | rest_framework/mixins.py | 5 | ||||
| -rw-r--r-- | rest_framework/tests/permissions.py | 20 | 
2 files changed, 25 insertions, 0 deletions
diff --git a/rest_framework/mixins.py b/rest_framework/mixins.py index 61ac225b..ce633112 100644 --- a/rest_framework/mixins.py +++ b/rest_framework/mixins.py @@ -9,6 +9,7 @@ from __future__ import unicode_literals  from django.http import Http404  from rest_framework import status  from rest_framework.response import Response +from rest_framework.request import clone_request  class CreateModelMixin(object): @@ -90,6 +91,10 @@ class UpdateModelMixin(object):          try:              self.object = self.get_object()          except Http404: +            # If this is a PUT-as-create operation, we need to ensure that +            # we have relevant permissions, as if this was a POST request. +            if not self.has_permission(clone_request(request, 'POST')): +                self.permission_denied(self.request)              created = True              success_status_code = status.HTTP_201_CREATED          else: diff --git a/rest_framework/tests/permissions.py b/rest_framework/tests/permissions.py index c04d2110..a7777b57 100644 --- a/rest_framework/tests/permissions.py +++ b/rest_framework/tests/permissions.py @@ -44,9 +44,14 @@ class ModelPermissionsIntegrationTests(TestCase):              Permission.objects.get(codename='change_basicmodel'),              Permission.objects.get(codename='delete_basicmodel')          ] +        user = User.objects.create_user('updateonly', 'updateonly@example.com', 'password') +        user.user_permissions = [ +            Permission.objects.get(codename='change_basicmodel'), +        ]          self.permitted_credentials = basic_auth_header('permitted', 'password')          self.disallowed_credentials = basic_auth_header('disallowed', 'password') +        self.updateonly_credentials = basic_auth_header('updateonly', 'password')          BasicModel(text='foo').save() @@ -87,3 +92,18 @@ class ModelPermissionsIntegrationTests(TestCase):          request = factory.delete('/1', HTTP_AUTHORIZATION=self.disallowed_credentials)          response = instance_view(request, pk=1)          self.assertEquals(response.status_code, status.HTTP_403_FORBIDDEN) + +    def test_has_put_as_create_permissions(self): +        # User only has update permissions - should be able to update an entity. +        request = factory.put('/1', json.dumps({'text': 'foobar'}), +                              content_type='application/json', +                              HTTP_AUTHORIZATION=self.updateonly_credentials) +        response = instance_view(request, pk='1') +        self.assertEquals(response.status_code, status.HTTP_200_OK) + +        # But if PUTing to a new entity, permission should be denied. +        request = factory.put('/2', json.dumps({'text': 'foobar'}), +                              content_type='application/json', +                              HTTP_AUTHORIZATION=self.updateonly_credentials) +        response = instance_view(request, pk='2') +        self.assertEquals(response.status_code, status.HTTP_403_FORBIDDEN)  | 
