diff options
| author | Tom Christie | 2013-09-10 21:00:13 +0100 | 
|---|---|---|
| committer | Tom Christie | 2013-09-10 21:00:13 +0100 | 
| commit | 5970baa20112921217ae4f2c2a9f175df25922db (patch) | |
| tree | 40f4ae8e6d2ffd841c31b6a55f98d9823516d61c /rest_framework/tests | |
| parent | 75fb4b02b40da04f16c6c288bbe20ea0bc0b4154 (diff) | |
| download | django-rest-framework-5970baa20112921217ae4f2c2a9f175df25922db.tar.bz2 | |
Tweaks and docs to object-level model permissions.
Diffstat (limited to 'rest_framework/tests')
| -rw-r--r-- | rest_framework/tests/test_permissions.py | 249 | 
1 files changed, 136 insertions, 113 deletions
diff --git a/rest_framework/tests/test_permissions.py b/rest_framework/tests/test_permissions.py index 2d866cd0..d08124f4 100644 --- a/rest_framework/tests/test_permissions.py +++ b/rest_framework/tests/test_permissions.py @@ -2,9 +2,10 @@ from __future__ import unicode_literals  from django.contrib.auth.models import User, Permission, Group  from django.db import models  from django.test import TestCase +from django.utils import unittest  from rest_framework import generics, status, permissions, authentication, HTTP_HEADER_ENCODING  from rest_framework.compat import guardian -from rest_framework.filters import ObjectPermissionReaderFilter +from rest_framework.filters import DjangoObjectPermissionsFilter  from rest_framework.test import APIRequestFactory  from rest_framework.tests.models import BasicModel  import base64 @@ -148,130 +149,152 @@ class BasicPermModel(models.Model):      class Meta:          app_label = 'tests'          permissions = ( -            ('read_basicpermmodel', 'Can view basic perm model'), +            ('view_basicpermmodel', 'Can view basic perm model'),              # add, change, delete built in to django          ) +# Custom object-level permission, that includes 'view' permissions +class ViewObjectPermissions(permissions.DjangoObjectPermissions): +    perms_map = { +        'GET': ['%(app_label)s.view_%(model_name)s'], +        'OPTIONS': ['%(app_label)s.view_%(model_name)s'], +        'HEAD': ['%(app_label)s.view_%(model_name)s'], +        'POST': ['%(app_label)s.add_%(model_name)s'], +        'PUT': ['%(app_label)s.change_%(model_name)s'], +        'PATCH': ['%(app_label)s.change_%(model_name)s'], +        'DELETE': ['%(app_label)s.delete_%(model_name)s'], +    } + +  class ObjectPermissionInstanceView(generics.RetrieveUpdateDestroyAPIView):      model = BasicPermModel      authentication_classes = [authentication.BasicAuthentication] -    permission_classes = [permissions.DjangoObjectLevelModelPermissions] +    permission_classes = [ViewObjectPermissions]  object_permissions_view = ObjectPermissionInstanceView.as_view() +  class ObjectPermissionListView(generics.ListAPIView):      model = BasicPermModel      authentication_classes = [authentication.BasicAuthentication] -    permission_classes = [permissions.DjangoObjectLevelModelPermissions] +    permission_classes = [ViewObjectPermissions]  object_permissions_list_view = ObjectPermissionListView.as_view() -if guardian: -    from guardian.shortcuts import assign_perm - -    class ObjectPermissionsIntegrationTests(TestCase): -        """ -        Integration tests for the object level permissions API. -        """ -        @classmethod -        def setUpClass(cls): -            # create users -            create = User.objects.create_user -            users = { -                'fullaccess': create('fullaccess', 'fullaccess@example.com', 'password'), -                'readonly': create('readonly', 'readonly@example.com', 'password'), -                'writeonly': create('writeonly', 'writeonly@example.com', 'password'), -                'deleteonly': create('deleteonly', 'deleteonly@example.com', 'password'), -            } - -            # give everyone model level permissions, as we are not testing those -            everyone = Group.objects.create(name='everyone') -            model_name = BasicPermModel._meta.module_name -            app_label = BasicPermModel._meta.app_label -            f = '{0}_{1}'.format -            perms = { -                'read':   f('read', model_name), -                'change': f('change', model_name), -                'delete': f('delete', model_name) -            } -            for perm in perms.values(): -                perm = '{0}.{1}'.format(app_label, perm) -                assign_perm(perm, everyone) -            everyone.user_set.add(*users.values()) - -            cls.perms = perms -            cls.users = users - -        def setUp(self): -            perms = self.perms -            users = self.users - -            # appropriate object level permissions -            readers = Group.objects.create(name='readers') -            writers = Group.objects.create(name='writers') -            deleters = Group.objects.create(name='deleters') - -            model = BasicPermModel.objects.create(text='foo') -             -            assign_perm(perms['read'], readers, model) -            assign_perm(perms['change'], writers, model) -            assign_perm(perms['delete'], deleters, model) - -            readers.user_set.add(users['fullaccess'], users['readonly']) -            writers.user_set.add(users['fullaccess'], users['writeonly']) -            deleters.user_set.add(users['fullaccess'], users['deleteonly']) - -            self.credentials = {} -            for user in users.values(): -                self.credentials[user.username] = basic_auth_header(user.username, 'password') - -        # Delete -        def test_can_delete_permissions(self): -            request = factory.delete('/1', HTTP_AUTHORIZATION=self.credentials['deleteonly']) -            response = object_permissions_view(request, pk='1') -            self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) - -        def test_cannot_delete_permissions(self): -            request = factory.delete('/1', HTTP_AUTHORIZATION=self.credentials['readonly']) -            response = object_permissions_view(request, pk='1') -            self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) - -        # Update -        def test_can_update_permissions(self): -            request = factory.patch('/1', {'text': 'foobar'}, format='json', -                HTTP_AUTHORIZATION=self.credentials['writeonly']) -            response = object_permissions_view(request, pk='1') -            self.assertEqual(response.status_code, status.HTTP_200_OK) -            self.assertEqual(response.data.get('text'), 'foobar') - -        def test_cannot_update_permissions(self): -            request = factory.patch('/1', {'text': 'foobar'}, format='json', -                HTTP_AUTHORIZATION=self.credentials['deleteonly']) -            response = object_permissions_view(request, pk='1') -            self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) - -        # Read -        def test_can_read_permissions(self): -            request = factory.get('/1', HTTP_AUTHORIZATION=self.credentials['readonly']) -            response = object_permissions_view(request, pk='1') -            self.assertEqual(response.status_code, status.HTTP_200_OK) - -        def test_cannot_read_permissions(self): -            request = factory.get('/1', HTTP_AUTHORIZATION=self.credentials['writeonly']) -            response = object_permissions_view(request, pk='1') -            self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) - -        # Read list -        def test_can_read_list_permissions(self): -            request = factory.get('/', HTTP_AUTHORIZATION=self.credentials['readonly']) -            object_permissions_list_view.cls.filter_backends = (ObjectPermissionReaderFilter,) -            response = object_permissions_list_view(request) -            self.assertEqual(response.status_code, status.HTTP_200_OK) -            self.assertEqual(response.data[0].get('id'), 1) - -        def test_cannot_read_list_permissions(self): -            request = factory.get('/', HTTP_AUTHORIZATION=self.credentials['writeonly']) -            object_permissions_list_view.cls.filter_backends = (ObjectPermissionReaderFilter,) -            response = object_permissions_list_view(request) -            self.assertEqual(response.status_code, status.HTTP_200_OK) -            self.assertListEqual(response.data, [])
\ No newline at end of file + +@unittest.skipUnless(guardian, 'django-guardian not installed') +class ObjectPermissionsIntegrationTests(TestCase): +    """ +    Integration tests for the object level permissions API. +    """ +    @classmethod +    def setUpClass(cls): +        from guardian.shortcuts import assign_perm + +        # create users +        create = User.objects.create_user +        users = { +            'fullaccess': create('fullaccess', 'fullaccess@example.com', 'password'), +            'readonly': create('readonly', 'readonly@example.com', 'password'), +            'writeonly': create('writeonly', 'writeonly@example.com', 'password'), +            'deleteonly': create('deleteonly', 'deleteonly@example.com', 'password'), +        } + +        # give everyone model level permissions, as we are not testing those +        everyone = Group.objects.create(name='everyone') +        model_name = BasicPermModel._meta.module_name +        app_label = BasicPermModel._meta.app_label +        f = '{0}_{1}'.format +        perms = { +            'view':   f('view', model_name), +            'change': f('change', model_name), +            'delete': f('delete', model_name) +        } +        for perm in perms.values(): +            perm = '{0}.{1}'.format(app_label, perm) +            assign_perm(perm, everyone) +        everyone.user_set.add(*users.values()) + +        cls.perms = perms +        cls.users = users + +    def setUp(self): +        from guardian.shortcuts import assign_perm +        perms = self.perms +        users = self.users + +        # appropriate object level permissions +        readers = Group.objects.create(name='readers') +        writers = Group.objects.create(name='writers') +        deleters = Group.objects.create(name='deleters') + +        model = BasicPermModel.objects.create(text='foo') +         +        assign_perm(perms['view'], readers, model) +        assign_perm(perms['change'], writers, model) +        assign_perm(perms['delete'], deleters, model) + +        readers.user_set.add(users['fullaccess'], users['readonly']) +        writers.user_set.add(users['fullaccess'], users['writeonly']) +        deleters.user_set.add(users['fullaccess'], users['deleteonly']) + +        self.credentials = {} +        for user in users.values(): +            self.credentials[user.username] = basic_auth_header(user.username, 'password') + +    # Delete +    def test_can_delete_permissions(self): +        request = factory.delete('/1', HTTP_AUTHORIZATION=self.credentials['deleteonly']) +        response = object_permissions_view(request, pk='1') +        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + +    def test_cannot_delete_permissions(self): +        request = factory.delete('/1', HTTP_AUTHORIZATION=self.credentials['readonly']) +        response = object_permissions_view(request, pk='1') +        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + +    # Update +    def test_can_update_permissions(self): +        request = factory.patch('/1', {'text': 'foobar'}, format='json', +            HTTP_AUTHORIZATION=self.credentials['writeonly']) +        response = object_permissions_view(request, pk='1') +        self.assertEqual(response.status_code, status.HTTP_200_OK) +        self.assertEqual(response.data.get('text'), 'foobar') + +    def test_cannot_update_permissions(self): +        request = factory.patch('/1', {'text': 'foobar'}, format='json', +            HTTP_AUTHORIZATION=self.credentials['deleteonly']) +        response = object_permissions_view(request, pk='1') +        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + +    def test_cannot_update_permissions_non_existing(self): +        request = factory.patch('/999', {'text': 'foobar'}, format='json', +            HTTP_AUTHORIZATION=self.credentials['deleteonly']) +        response = object_permissions_view(request, pk='999') +        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + +    # Read +    def test_can_read_permissions(self): +        request = factory.get('/1', HTTP_AUTHORIZATION=self.credentials['readonly']) +        response = object_permissions_view(request, pk='1') +        self.assertEqual(response.status_code, status.HTTP_200_OK) + +    def test_cannot_read_permissions(self): +        request = factory.get('/1', HTTP_AUTHORIZATION=self.credentials['writeonly']) +        response = object_permissions_view(request, pk='1') +        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + +    # Read list +    def test_can_read_list_permissions(self): +        request = factory.get('/', HTTP_AUTHORIZATION=self.credentials['readonly']) +        object_permissions_list_view.cls.filter_backends = (DjangoObjectPermissionsFilter,) +        response = object_permissions_list_view(request) +        self.assertEqual(response.status_code, status.HTTP_200_OK) +        self.assertEqual(response.data[0].get('id'), 1) + +    def test_cannot_read_list_permissions(self): +        request = factory.get('/', HTTP_AUTHORIZATION=self.credentials['writeonly']) +        object_permissions_list_view.cls.filter_backends = (DjangoObjectPermissionsFilter,) +        response = object_permissions_list_view(request) +        self.assertEqual(response.status_code, status.HTTP_200_OK) +        self.assertListEqual(response.data, [])  | 
