diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index 24bb42ea5..3c5c4a2f4 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals from django.http import Http404 from django.utils import six +from django.utils.translation import ugettext_lazy as _ from rest_framework import exceptions @@ -85,6 +86,16 @@ class OR: def __init__(self, op1, op2): self.op1 = op1 self.op2 = op2 + self.message1 = op1.message if hasattr(op1, 'message') else None + self.message2 = op2.message if hasattr(op2, 'message') else None + self.message = self.message1 or self.message2 + if self.message1 and self.message2: + self.message = _('"{message1}" OR "{message2}"').format( + message1=self.message1, + message2=self.message2, + ) + else: + self.message = self.message1 or self.message2 def has_permission(self, request, view): return ( diff --git a/tests/test_permissions.py b/tests/test_permissions.py index b0d917aa9..a87a9eff8 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -522,6 +522,18 @@ class DeniedViewWithDetailAND3(PermissionInstanceView): permission_classes = (BasicPermWithDetail & AnotherBasicPermWithDetail,) +class DeniedViewWithDetailOR1(PermissionInstanceView): + permission_classes = (BasicPerm | BasicPermWithDetail,) + + +class DeniedViewWithDetailOR2(PermissionInstanceView): + permission_classes = (BasicPermWithDetail | BasicPerm,) + + +class DeniedViewWithDetailOR3(PermissionInstanceView): + permission_classes = (BasicPermWithDetail | AnotherBasicPermWithDetail,) + + class DeniedObjectView(PermissionInstanceView): permission_classes = (BasicObjectPerm,) @@ -542,6 +554,18 @@ class DeniedObjectViewWithDetailAND3(PermissionInstanceView): permission_classes = (AnotherBasicObjectPermWithDetail & BasicObjectPermWithDetail,) +class DeniedObjectViewWithDetailOR1(PermissionInstanceView): + permission_classes = (BasicObjectPerm | BasicObjectPermWithDetail,) + + +class DeniedObjectViewWithDetailOR2(PermissionInstanceView): + permission_classes = (BasicObjectPermWithDetail | BasicObjectPerm,) + + +class DeniedObjectViewWithDetailOR3(PermissionInstanceView): + permission_classes = (BasicObjectPermWithDetail | AnotherBasicObjectPermWithDetail,) + + denied_view = DeniedView.as_view() denied_view_with_detail = DeniedViewWithDetail.as_view() @@ -550,6 +574,10 @@ denied_view_with_detail_and_1 = DeniedViewWithDetailAND1.as_view() denied_view_with_detail_and_2 = DeniedViewWithDetailAND2.as_view() denied_view_with_detail_and_3 = DeniedViewWithDetailAND3.as_view() +denied_view_with_detail_or_1 = DeniedViewWithDetailOR1.as_view() +denied_view_with_detail_or_2 = DeniedViewWithDetailOR2.as_view() +denied_view_with_detail_or_3 = DeniedViewWithDetailOR3.as_view() + denied_object_view = DeniedObjectView.as_view() denied_object_view_with_detail = DeniedObjectViewWithDetail.as_view() @@ -558,6 +586,10 @@ denied_object_view_with_detail_and_1 = DeniedObjectViewWithDetailAND1.as_view() denied_object_view_with_detail_and_2 = DeniedObjectViewWithDetailAND2.as_view() denied_object_view_with_detail_and_3 = DeniedObjectViewWithDetailAND3.as_view() +denied_object_view_with_detail_or_1 = DeniedObjectViewWithDetailOR1.as_view() +denied_object_view_with_detail_or_2 = DeniedObjectViewWithDetailOR2.as_view() +denied_object_view_with_detail_or_3 = DeniedObjectViewWithDetailOR3.as_view() + class CustomPermissionsTests(TestCase): def setUp(self): @@ -596,6 +628,25 @@ class CustomPermissionsTests(TestCase): self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual(detail, CUSTOM_MESSAGE_1) + def test_permission_denied_with_custom_detail_or_1(self): + response = denied_view_with_detail_or_1(self.request, pk=1) + detail = response.data.get('detail') + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(detail, CUSTOM_MESSAGE_1) + + def test_permission_denied_with_custom_detail_or_2(self): + response = denied_view_with_detail_or_2(self.request, pk=1) + detail = response.data.get('detail') + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(detail, CUSTOM_MESSAGE_1) + + def test_permission_denied_with_custom_detail_or_3(self): + response = denied_view_with_detail_or_3(self.request, pk=1) + detail = response.data.get('detail') + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + expected_message = '"{0}" OR "{1}"'.format(CUSTOM_MESSAGE_1, CUSTOM_MESSAGE_2) + self.assertEqual(detail, expected_message) + def test_permission_denied_for_object(self): response = denied_object_view(self.request, pk=1) detail = response.data.get('detail')