Fix unhandled Http404, PermissionDenied in schema generation (#4645) (#4646)

This commit is contained in:
Andrzej Pragacz 2016-11-02 10:04:01 +01:00 committed by Tom Christie
parent 2bf082a623
commit 45e058d7ba
2 changed files with 70 additions and 2 deletions

View File

@ -4,6 +4,8 @@ from importlib import import_module
from django.conf import settings
from django.contrib.admindocs.views import simplify_regex
from django.core.exceptions import PermissionDenied
from django.http import Http404
from django.utils import six
from django.utils.encoding import force_text, smart_text
@ -339,7 +341,7 @@ class SchemaGenerator(object):
try:
view.check_permissions(view.request)
except exceptions.APIException:
except (exceptions.APIException, Http404, PermissionDenied):
return False
return True

View File

@ -1,17 +1,22 @@
import unittest
from django.conf.urls import include, url
from django.core.exceptions import PermissionDenied
from django.http import Http404
from django.test import TestCase, override_settings
from rest_framework import filters, pagination, permissions, serializers
from rest_framework.compat import coreapi
from rest_framework.decorators import detail_route, list_route
from rest_framework.request import Request
from rest_framework.routers import DefaultRouter
from rest_framework.schemas import SchemaGenerator, get_schema_view
from rest_framework.test import APIClient
from rest_framework.test import APIClient, APIRequestFactory
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
factory = APIRequestFactory()
class MockUser(object):
def is_authenticated(self):
@ -215,6 +220,32 @@ class TestRouterGeneratedSchema(TestCase):
self.assertEqual(response.data, expected)
class DenyAllUsingHttp404(permissions.BasePermission):
def has_permission(self, request, view):
raise Http404()
def has_object_permission(self, request, view, obj):
raise Http404()
class DenyAllUsingPermissionDenied(permissions.BasePermission):
def has_permission(self, request, view):
raise PermissionDenied()
def has_object_permission(self, request, view, obj):
raise PermissionDenied()
class Http404ExampleViewSet(ExampleViewSet):
permission_classes = [DenyAllUsingHttp404]
class PermissionDeniedExampleViewSet(ExampleViewSet):
permission_classes = [DenyAllUsingPermissionDenied]
class ExampleListView(APIView):
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
@ -337,6 +368,41 @@ class TestSchemaGeneratorNotAtRoot(TestCase):
self.assertEqual(schema, expected)
@unittest.skipUnless(coreapi, 'coreapi is not installed')
class TestSchemaGeneratorWithRestrictedViewSets(TestCase):
def setUp(self):
router = DefaultRouter()
router.register('example1', Http404ExampleViewSet, base_name='example1')
router.register('example2', PermissionDeniedExampleViewSet, base_name='example2')
self.patterns = [
url('^example/?$', ExampleListView.as_view()),
url(r'^', include(router.urls))
]
def test_schema_for_regular_views(self):
"""
Ensure that schema generation works for ViewSet classes
with permission classes raising exceptions.
"""
generator = SchemaGenerator(title='Example API', patterns=self.patterns)
request = factory.get('/')
schema = generator.get_schema(Request(request))
expected = coreapi.Document(
url='',
title='Example API',
content={
'example': {
'list': coreapi.Link(
url='/example/',
action='get',
fields=[]
),
},
}
)
self.assertEqual(schema, expected)
@unittest.skipUnless(coreapi, 'coreapi is not installed')
class Test4605Regression(TestCase):
def test_4605_regression(self):