diff --git a/docs/topics/third-party-resources.md b/docs/topics/third-party-resources.md index c4ac88255..cc29c4334 100644 --- a/docs/topics/third-party-resources.md +++ b/docs/topics/third-party-resources.md @@ -253,6 +253,7 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque * [django-rest-framework-braces][django-rest-framework-braces] - Collection of utilities for working with Django Rest Framework. The most notable ones are [FormSerializer](https://django-rest-framework-braces.readthedocs.org/en/latest/overview.html#formserializer) and [SerializerForm](https://django-rest-framework-braces.readthedocs.org/en/latest/overview.html#serializerform), which are adapters between DRF serializers and Django forms. * [drf-haystack][drf-haystack] - Haystack search for Django Rest Framework * [django-rest-framework-version-transforms][django-rest-framework-version-transforms] - Enables the use of delta transformations for versioning of DRF resource representations. +* [django-rest-messaging][django-rest-messaging], [django-rest-messaging-centrifugo][django-rest-messaging-centrifugo] and [django-rest-messaging-js][django-rest-messaging-js] - A real-time pluggable messaging service using DRM. ## Other Resources @@ -357,3 +358,6 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque [django-rest-framework-version-transforms]: https://github.com/mrhwick/django-rest-framework-version-transforms [djangorestframework-jsonapi]: https://github.com/django-json-api/django-rest-framework-json-api [html-json-forms]: https://github.com/wq/html-json-forms +[django-rest-messaging]: https://github.com/raphaelgyory/django-rest-messaging +[django-rest-messaging-centrifugo]: https://github.com/raphaelgyory/django-rest-messaging-centrifugo +[django-rest-messaging-js]: https://github.com/raphaelgyory/django-rest-messaging-js diff --git a/rest_framework/views.py b/rest_framework/views.py index c13e74447..41d108e53 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -162,7 +162,7 @@ class APIView(View): """ If request is not permitted, determine what kind of exception to raise. """ - if not request.successful_authenticator: + if request.authenticators and not request.successful_authenticator: raise exceptions.NotAuthenticated() raise exceptions.PermissionDenied(detail=message) diff --git a/tests/test_authentication.py b/tests/test_authentication.py index 285a3210c..70eea3132 100644 --- a/tests/test_authentication.py +++ b/tests/test_authentication.py @@ -321,3 +321,28 @@ class FailingAuthAccessedInRenderer(TestCase): response = self.view(request) content = response.render().content self.assertEqual(content, b'not authenticated') + + +class NoAuthenticationClassesTests(TestCase): + def test_permission_message_with_no_authentication_classes(self): + """ + An unauthenticated request made against a view that containes no + `authentication_classes` but do contain `permissions_classes` the error + code returned should be 403 with the exception's message. + """ + + class DummyPermission(permissions.BasePermission): + message = 'Dummy permission message' + + def has_permission(self, request, view): + return False + + request = factory.get('/') + view = MockView.as_view( + authentication_classes=(), + permission_classes=(DummyPermission,), + ) + response = view(request) + self.assertEqual(response.status_code, + status.HTTP_403_FORBIDDEN) + self.assertEqual(response.data, {'detail': 'Dummy permission message'})