Skip to content
Snippets Groups Projects
Verified Commit 367014f7 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Added owner permission to check user has the right to read/update object

parent 3e277aad
No related branches found
No related tags found
No related merge requests found
import operator
from django.conf import settings from django.conf import settings
from django.http import Http404
from rest_framework.permissions import BasePermission, DjangoModelPermissions from rest_framework.permissions import BasePermission, DjangoModelPermissions
...@@ -20,3 +23,39 @@ class HasModelPermission(DjangoModelPermissions): ...@@ -20,3 +23,39 @@ class HasModelPermission(DjangoModelPermissions):
""" """
def get_required_permissions(self, method, model_cls): def get_required_permissions(self, method, model_cls):
return super().get_required_permissions(method, self.model) return super().get_required_permissions(method, self.model)
class OwnerPermission(BasePermission):
"""
Ensure the request user is the owner of the object.
Usage:
class MyView(APIView):
model = MyModel
permission_classes = [OwnerPermission]
owner_field = 'owner'
owner_checks = ['read', 'write']
"""
perms_map = {
'GET': 'read',
'OPTIONS': 'read',
'HEAD': 'read',
'POST': 'write',
'PUT': 'write',
'PATCH': 'write',
'DELETE': 'write',
}
def has_object_permission(self, request, view, obj):
method_check = self.perms_map[request.method]
owner_checks = getattr(view, 'owner_checks', ['read', 'write'])
if method_check not in owner_checks:
# check not enabled
return True
owner_field = getattr(view, 'owner_field', 'user')
owner = operator.attrgetter(owner_field)(obj)
if owner != request.user:
raise Http404
return True
import pytest
from rest_framework.views import APIView
from django.contrib.auth.models import AnonymousUser
from django.http import Http404
from funkwhale_api.common import permissions
def test_owner_permission_owner_field_ok(nodb_factories, api_request):
playlist = nodb_factories['playlists.Playlist']()
view = APIView.as_view()
permission = permissions.OwnerPermission()
request = api_request.get('/')
setattr(request, 'user', playlist.user)
check = permission.has_object_permission(request, view, playlist)
assert check is True
def test_owner_permission_owner_field_not_ok(nodb_factories, api_request):
playlist = nodb_factories['playlists.Playlist']()
view = APIView.as_view()
permission = permissions.OwnerPermission()
request = api_request.get('/')
setattr(request, 'user', AnonymousUser())
with pytest.raises(Http404):
permission.has_object_permission(request, view, playlist)
def test_owner_permission_read_only(nodb_factories, api_request):
playlist = nodb_factories['playlists.Playlist']()
view = APIView.as_view()
setattr(view, 'owner_checks', ['write'])
permission = permissions.OwnerPermission()
request = api_request.get('/')
setattr(request, 'user', AnonymousUser())
check = permission.has_object_permission(request, view, playlist)
assert check is True
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment