mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-03-27 13:24:26 +03:00
some properly failing tests, set up for standard permissions
This commit is contained in:
parent
4a9dcfa760
commit
b07de86ad3
|
@ -153,7 +153,7 @@ class DjangoModelPermissionsOrAnonReadOnly(DjangoModelPermissions):
|
||||||
|
|
||||||
class DjangoObjectLevelModelPermissions(DjangoModelPermissions):
|
class DjangoObjectLevelModelPermissions(DjangoModelPermissions):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
assert guardian, 'Using DjangoObjectLevelModelPermissions, but guardian is not installed'
|
assert guardian, 'Using DjangoObjectLevelModelPermissions, but django-guardian is not installed'
|
||||||
|
|
||||||
|
|
||||||
class TokenHasReadWriteScope(BasePermission):
|
class TokenHasReadWriteScope(BasePermission):
|
||||||
|
|
|
@ -123,6 +123,17 @@ else:
|
||||||
'provider.oauth2',
|
'provider.oauth2',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# guardian is optional
|
||||||
|
try:
|
||||||
|
import guardian
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
ANONYMOUS_USER_ID = -1
|
||||||
|
INSTALLED_APPS += (
|
||||||
|
'guardian',
|
||||||
|
)
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
PASSWORD_HASHERS = (
|
PASSWORD_HASHERS = (
|
||||||
|
|
|
@ -3,17 +3,14 @@ from django.contrib.auth.models import User, Permission
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from rest_framework import generics, status, permissions, authentication, HTTP_HEADER_ENCODING
|
from rest_framework import generics, status, permissions, authentication, HTTP_HEADER_ENCODING
|
||||||
from rest_framework.test import APIRequestFactory
|
|
||||||
from rest_framework.compat import guardian
|
from rest_framework.compat import guardian
|
||||||
|
from rest_framework.test import APIRequestFactory
|
||||||
|
from rest_framework.tests.models import BasicModel
|
||||||
|
from rest_framework.settings import api_settings
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
factory = APIRequestFactory()
|
factory = APIRequestFactory()
|
||||||
|
|
||||||
|
|
||||||
class BasicModel(models.Model):
|
|
||||||
text = models.CharField(max_length=100)
|
|
||||||
|
|
||||||
|
|
||||||
class RootView(generics.ListCreateAPIView):
|
class RootView(generics.ListCreateAPIView):
|
||||||
model = BasicModel
|
model = BasicModel
|
||||||
authentication_classes = [authentication.BasicAuthentication]
|
authentication_classes = [authentication.BasicAuthentication]
|
||||||
|
@ -145,45 +142,67 @@ class ModelPermissionsIntegrationTests(TestCase):
|
||||||
self.assertEqual(list(response.data['actions'].keys()), ['PUT'])
|
self.assertEqual(list(response.data['actions'].keys()), ['PUT'])
|
||||||
|
|
||||||
|
|
||||||
class OwnerModel(models.Model):
|
class BasicPermModel(BasicModel):
|
||||||
text = models.CharField(max_length=100)
|
|
||||||
owner = models.ForeignKey(User)
|
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = 'tests'
|
||||||
|
permissions = (
|
||||||
|
('read_basicpermmodel', "Can view basic perm model"),
|
||||||
|
# add, change, delete built in to django
|
||||||
|
)
|
||||||
|
|
||||||
class IsOwnerPermission(permissions.BasePermission):
|
class ObjectPermissionInstanceView(generics.RetrieveUpdateDestroyAPIView):
|
||||||
def has_object_permission(self, request, view, obj):
|
model = BasicModel
|
||||||
return request.user == obj.owner
|
|
||||||
|
|
||||||
|
|
||||||
class OwnerInstanceView(generics.RetrieveUpdateDestroyAPIView):
|
|
||||||
model = OwnerModel
|
|
||||||
authentication_classes = [authentication.BasicAuthentication]
|
authentication_classes = [authentication.BasicAuthentication]
|
||||||
permission_classes = [IsOwnerPermission]
|
permission_classes = [permissions.DjangoObjectLevelModelPermissions]
|
||||||
|
|
||||||
|
|
||||||
owner_instance_view = OwnerInstanceView.as_view()
|
object_permissions_view = ObjectPermissionInstanceView.as_view()
|
||||||
|
|
||||||
|
if guardian:
|
||||||
|
class ObjectPermissionsIntegrationTests(TestCase):
|
||||||
|
"""
|
||||||
|
Integration tests for the object level permissions API.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# create users
|
||||||
|
User.objects.create_user('no_permission', 'no_permission@example.com', 'password')
|
||||||
|
reader = User.objects.create_user('reader', 'reader@example.com', 'password')
|
||||||
|
writer = User.objects.create_user('writer', 'writer@example.com', 'password')
|
||||||
|
full_access = User.objects.create_user('full_access', 'full_access@example.com', 'password')
|
||||||
|
|
||||||
|
model = BasicPermModel.objects.create(text='foo')
|
||||||
|
|
||||||
|
# assign permissions appropriately
|
||||||
|
from guardian.shortcuts import assign_perm
|
||||||
|
|
||||||
|
read = "read_basicpermmodel"
|
||||||
|
write = "change_basicpermmodel"
|
||||||
|
delete = "delete_basicpermmodel"
|
||||||
|
app_label = 'tests.'
|
||||||
|
# model level permissions
|
||||||
|
assign_perm(app_label + delete, full_access, obj=model)
|
||||||
|
(assign_perm(app_label + write, user, obj=model) for user in (writer, full_access))
|
||||||
|
(assign_perm(app_label + read, user, obj=model) for user in (reader, writer, full_access))
|
||||||
|
|
||||||
|
# object level permissions
|
||||||
|
assign_perm(delete, full_access, obj=model)
|
||||||
|
(assign_perm(write, user, obj=model) for user in (writer, full_access))
|
||||||
|
(assign_perm(read, user, obj=model) for user in (reader, writer, full_access))
|
||||||
|
|
||||||
|
self.no_permission_credentials = basic_auth_header('no_permission', 'password')
|
||||||
|
self.reader_credentials = basic_auth_header('reader', 'password')
|
||||||
|
self.writer_credentials = basic_auth_header('writer', 'password')
|
||||||
|
self.full_access_credentials = basic_auth_header('full_access', 'password')
|
||||||
|
|
||||||
|
|
||||||
class ObjectPermissionsIntegrationTests(TestCase):
|
def test_has_delete_permissions(self):
|
||||||
"""
|
request = factory.delete('/1', HTTP_AUTHORIZATION=self.full_access_credentials)
|
||||||
Integration tests for the object level permissions API.
|
response = object_permissions_view(request, pk='1')
|
||||||
"""
|
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
def setUp(self):
|
def test_no_delete_permissions(self):
|
||||||
User.objects.create_user('not_owner', 'not_owner@example.com', 'password')
|
request = factory.delete('/1', HTTP_AUTHORIZATION=self.writer_credentials)
|
||||||
user = User.objects.create_user('owner', 'owner@example.com', 'password')
|
response = object_permissions_view(request, pk='1')
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
self.not_owner_credentials = basic_auth_header('not_owner', 'password')
|
|
||||||
self.owner_credentials = basic_auth_header('owner', 'password')
|
|
||||||
|
|
||||||
OwnerModel(text='foo', owner=user).save()
|
|
||||||
|
|
||||||
def test_owner_has_delete_permissions(self):
|
|
||||||
request = factory.delete('/1', HTTP_AUTHORIZATION=self.owner_credentials)
|
|
||||||
response = owner_instance_view(request, pk='1')
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
|
||||||
|
|
||||||
def test_non_owner_does_not_have_delete_permissions(self):
|
|
||||||
request = factory.delete('/1', HTTP_AUTHORIZATION=self.not_owner_credentials)
|
|
||||||
response = owner_instance_view(request, pk='1')
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
|
||||||
|
|
8
tox.ini
8
tox.ini
|
@ -25,6 +25,7 @@ deps = https://www.djangoproject.com/download/1.6a1/tarball/
|
||||||
django-oauth-plus==2.0
|
django-oauth-plus==2.0
|
||||||
oauth2==1.5.211
|
oauth2==1.5.211
|
||||||
django-oauth2-provider==0.2.4
|
django-oauth2-provider==0.2.4
|
||||||
|
django-guardian==1.1.1
|
||||||
|
|
||||||
[testenv:py2.6-django1.6]
|
[testenv:py2.6-django1.6]
|
||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
|
@ -34,6 +35,7 @@ deps = https://www.djangoproject.com/download/1.6a1/tarball/
|
||||||
django-oauth-plus==2.0
|
django-oauth-plus==2.0
|
||||||
oauth2==1.5.211
|
oauth2==1.5.211
|
||||||
django-oauth2-provider==0.2.4
|
django-oauth2-provider==0.2.4
|
||||||
|
django-guardian==1.1.1
|
||||||
|
|
||||||
[testenv:py3.3-django1.5]
|
[testenv:py3.3-django1.5]
|
||||||
basepython = python3.3
|
basepython = python3.3
|
||||||
|
@ -55,6 +57,7 @@ deps = django==1.5
|
||||||
django-oauth-plus==2.0
|
django-oauth-plus==2.0
|
||||||
oauth2==1.5.211
|
oauth2==1.5.211
|
||||||
django-oauth2-provider==0.2.3
|
django-oauth2-provider==0.2.3
|
||||||
|
django-guardian==1.1.1
|
||||||
|
|
||||||
[testenv:py2.6-django1.5]
|
[testenv:py2.6-django1.5]
|
||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
|
@ -64,6 +67,7 @@ deps = django==1.5
|
||||||
django-oauth-plus==2.0
|
django-oauth-plus==2.0
|
||||||
oauth2==1.5.211
|
oauth2==1.5.211
|
||||||
django-oauth2-provider==0.2.3
|
django-oauth2-provider==0.2.3
|
||||||
|
django-guardian==1.1.1
|
||||||
|
|
||||||
[testenv:py2.7-django1.4]
|
[testenv:py2.7-django1.4]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
|
@ -73,6 +77,7 @@ deps = django==1.4.3
|
||||||
django-oauth-plus==2.0
|
django-oauth-plus==2.0
|
||||||
oauth2==1.5.211
|
oauth2==1.5.211
|
||||||
django-oauth2-provider==0.2.3
|
django-oauth2-provider==0.2.3
|
||||||
|
django-guardian==1.1.1
|
||||||
|
|
||||||
[testenv:py2.6-django1.4]
|
[testenv:py2.6-django1.4]
|
||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
|
@ -82,6 +87,7 @@ deps = django==1.4.3
|
||||||
django-oauth-plus==2.0
|
django-oauth-plus==2.0
|
||||||
oauth2==1.5.211
|
oauth2==1.5.211
|
||||||
django-oauth2-provider==0.2.3
|
django-oauth2-provider==0.2.3
|
||||||
|
django-guardian==1.1.1
|
||||||
|
|
||||||
[testenv:py2.7-django1.3]
|
[testenv:py2.7-django1.3]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
|
@ -91,6 +97,7 @@ deps = django==1.3.5
|
||||||
django-oauth-plus==2.0
|
django-oauth-plus==2.0
|
||||||
oauth2==1.5.211
|
oauth2==1.5.211
|
||||||
django-oauth2-provider==0.2.3
|
django-oauth2-provider==0.2.3
|
||||||
|
django-guardian==1.1.1
|
||||||
|
|
||||||
[testenv:py2.6-django1.3]
|
[testenv:py2.6-django1.3]
|
||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
|
@ -100,3 +107,4 @@ deps = django==1.3.5
|
||||||
django-oauth-plus==2.0
|
django-oauth-plus==2.0
|
||||||
oauth2==1.5.211
|
oauth2==1.5.211
|
||||||
django-oauth2-provider==0.2.3
|
django-oauth2-provider==0.2.3
|
||||||
|
django-guardian==1.1.1
|
||||||
|
|
Loading…
Reference in New Issue
Block a user