2020
2121CUSTOM_MESSAGE_1 = 'Custom: You cannot access this resource'
2222CUSTOM_MESSAGE_2 = 'Custom: You do not have permission to view this resource'
23+ INVERTED_MESSAGE = 'Inverted: Your account already active'
2324
2425
2526class BasicSerializer (serializers .ModelSerializer ):
@@ -458,6 +459,7 @@ def has_permission(self, request, view):
458459
459460class BasicPermWithDetail (permissions .BasePermission ):
460461 message = CUSTOM_MESSAGE_1
462+ message_inverted = INVERTED_MESSAGE
461463 code = 'permission_denied_custom'
462464
463465 def has_permission (self , request , view ):
@@ -478,6 +480,7 @@ def has_object_permission(self, request, view, obj):
478480
479481class BasicObjectPermWithDetail (permissions .BasePermission ):
480482 message = CUSTOM_MESSAGE_1
483+ message_inverted = INVERTED_MESSAGE
481484 code = 'permission_denied_custom'
482485
483486 def has_object_permission (self , request , view , obj ):
@@ -528,6 +531,10 @@ class DeniedViewWithDetailOR3(PermissionInstanceView):
528531 permission_classes = (BasicPermWithDetail | AnotherBasicPermWithDetail ,)
529532
530533
534+ class DeniedViewWithDetailNOT (PermissionInstanceView ):
535+ permission_classes = (~ BasicPermWithDetail ,)
536+
537+
531538class DeniedObjectView (PermissionInstanceView ):
532539 permission_classes = (BasicObjectPerm ,)
533540
@@ -560,6 +567,10 @@ class DeniedObjectViewWithDetailOR3(PermissionInstanceView):
560567 permission_classes = (BasicObjectPermWithDetail | AnotherBasicObjectPermWithDetail ,)
561568
562569
570+ class DeniedObjectViewWithDetailNOT (PermissionInstanceView ):
571+ permission_classes = (~ BasicObjectPermWithDetail ,)
572+
573+
563574denied_view = DeniedView .as_view ()
564575
565576denied_view_with_detail = DeniedViewWithDetail .as_view ()
@@ -572,6 +583,8 @@ class DeniedObjectViewWithDetailOR3(PermissionInstanceView):
572583denied_view_with_detail_or_2 = DeniedViewWithDetailOR2 .as_view ()
573584denied_view_with_detail_or_3 = DeniedViewWithDetailOR3 .as_view ()
574585
586+ denied_view_with_detail_not = DeniedObjectViewWithDetailNOT .as_view ()
587+
575588denied_object_view = DeniedObjectView .as_view ()
576589
577590denied_object_view_with_detail = DeniedObjectViewWithDetail .as_view ()
@@ -584,6 +597,8 @@ class DeniedObjectViewWithDetailOR3(PermissionInstanceView):
584597denied_object_view_with_detail_or_2 = DeniedObjectViewWithDetailOR2 .as_view ()
585598denied_object_view_with_detail_or_3 = DeniedObjectViewWithDetailOR3 .as_view ()
586599
600+ denied_object_view_with_detail_not = DeniedObjectViewWithDetailNOT .as_view ()
601+
587602
588603class CustomPermissionsTests (TestCase ):
589604 def setUp (self ):
@@ -644,6 +659,12 @@ def test_permission_denied_with_custom_detail_or_3(self):
644659 expected_message = '"{0}" OR "{1}"' .format (CUSTOM_MESSAGE_1 , CUSTOM_MESSAGE_2 )
645660 self .assertEqual (detail , expected_message )
646661
662+ def test_permission_denied_with_custom_detail_not (self ):
663+ response = denied_view_with_detail_not (self .request , pk = 1 )
664+ detail = response .data .get ('detail' )
665+ self .assertEqual (response .status_code , status .HTTP_403_FORBIDDEN )
666+ self .assertEqual (detail , INVERTED_MESSAGE )
667+
647668 def test_permission_denied_for_object (self ):
648669 response = denied_object_view (self .request , pk = 1 )
649670 detail = response .data .get ('detail' )
@@ -695,6 +716,12 @@ def test_permission_denied_for_object_with_custom_detail_or_3(self):
695716 expected_message = '"{0}" OR "{1}"' .format (CUSTOM_MESSAGE_1 , CUSTOM_MESSAGE_2 )
696717 self .assertEqual (detail , expected_message )
697718
719+ def test_permission_denied_for_object_with_custom_detail_not (self ):
720+ response = denied_object_view_with_detail_not (self .request , pk = 1 )
721+ detail = response .data .get ('detail' )
722+ self .assertEqual (response .status_code , status .HTTP_403_FORBIDDEN )
723+ self .assertEqual (detail , INVERTED_MESSAGE )
724+
698725
699726class PermissionsCompositionTests (TestCase ):
700727
0 commit comments