I've created a special permission class which checks that the current user 
is either accessing the resource readonly, or is an admin user, or is a 
specific user according to a different property on the object.

When I try to view the resource on the browsable API, I get a permission 
denied error. Strangely, when I looked at request.method in the permission 
class at the time of the exception, I was seeing POST rather than GET. I 
debugged using pdb and saw that the view was basically being called twice-- 
once with request.method == GET, once with request.method == POST. The 
second permission check throws an exception which breaks the page.

According to the pdb listings, the reason this happens is the response 
template needs to be able to render a POST, PUT, and PATCH form. It seems 
it might be calling the request again in order to see what the resource 
"shape" is, and/or to double check permissions. But it seems strange that 
the exception is allowed to go all the way through rather than being caught 
in that template (and maybe choosing not to render the form for users who 
have GET permission but not POST permission).

I have to assume this isn't the intentional design, and I might be 
accidentally tripping something up with some of the renderers etc. I am 
using. I am using DRF and also the Django REST Framework JSON API library.

My views:

class JamSessionRelationshipView(RelationshipView):
    queryset = JamSession.objects.all()

class JamSessionMembersRelationshipView(JamSessionRelationshipView):
    permission_classes = [IsConductorOrAdminOrReadOnly]

My permission class:

class IsConductorOrAdminOrReadOnly(permissions.BasePermission):
    message = "User must be an admin or conductor to modify the jam session 
members."

    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True

        if request.user.is_staff:
            return True

        return request.user == obj.conductor

My DRF settings:

REST_FRAMEWORK = {
    'PAGE_SIZE': 10,
    'EXCEPTION_HANDLER': 
'rest_framework_json_api.exceptions.exception_handler',
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    ],
    'DEFAULT_PAGINATION_CLASS':
        'rest_framework_json_api.pagination.JsonApiLimitOffsetPagination',
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework_json_api.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser'
    ),
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework_json_api.renderers.JSONRenderer',
        # If you're performance testing, you will want to use the 
browseable API
        # without forms, as the forms can generate their own queries.
        # If performance testing, enable:
        # 'example.utils.BrowsableAPIRendererWithoutForms',
        # Otherwise, to play around with the browseable API, enable:
        'rest_framework.renderers.BrowsableAPIRenderer'
    ),
    'DEFAULT_METADATA_CLASS': 
'rest_framework_json_api.metadata.JSONAPIMetadata',
    'DEFAULT_FILTER_BACKENDS': (
        'rest_framework_json_api.filters.QueryParameterValidationFilter',
        'rest_framework_json_api.filters.OrderingFilter',
        #'rest_framework_json_api.django_filters.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter',
    ),
    'SEARCH_PARAM': 'filter[search]',
    'TEST_REQUEST_RENDERER_CLASSES': (
        'rest_framework_json_api.renderers.JSONRenderer',
    ),
    'TEST_REQUEST_DEFAULT_FORMAT': 'vnd.api+json',
}

Please let me know if I can provide any other helpful information.

Thanks,
Kevin

-- 
You received this message because you are subscribed to the Google Groups 
"Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-rest-framework+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-rest-framework/ceafe69f-7c1a-48b5-8d75-44e5ba2b2854n%40googlegroups.com.

Reply via email to