Additional permissions checks on playlist views
This commit is contained in:
parent
4f7fa09a78
commit
9a909798e7
api
|
@ -1,9 +1,11 @@
|
|||
from rest_framework import generics, mixins, viewsets
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.permissions import IsAuthenticatedOrReadOnly
|
||||
|
||||
from funkwhale_api.music.models import Track
|
||||
from funkwhale_api.common.permissions import ConditionalAuthentication
|
||||
from funkwhale_api.common import permissions
|
||||
from funkwhale_api.common import fields
|
||||
|
||||
from . import models
|
||||
from . import serializers
|
||||
|
@ -12,24 +14,22 @@ from . import serializers
|
|||
class PlaylistViewSet(
|
||||
mixins.RetrieveModelMixin,
|
||||
mixins.CreateModelMixin,
|
||||
mixins.UpdateModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
mixins.ListModelMixin,
|
||||
viewsets.GenericViewSet):
|
||||
|
||||
serializer_class = serializers.PlaylistSerializer
|
||||
queryset = (models.Playlist.objects.all())
|
||||
permission_classes = [ConditionalAuthentication]
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
instance = self.perform_create(serializer)
|
||||
serializer = self.get_serializer(instance=instance)
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||
permission_classes = [
|
||||
permissions.ConditionalAuthentication,
|
||||
permissions.OwnerPermission,
|
||||
IsAuthenticatedOrReadOnly,
|
||||
]
|
||||
|
||||
def get_queryset(self):
|
||||
return self.queryset.filter(user=self.request.user)
|
||||
return self.queryset.filter(
|
||||
fields.privacy_level_query(self.request.user))
|
||||
|
||||
def perform_create(self, serializer):
|
||||
return serializer.save(
|
||||
|
@ -41,23 +41,39 @@ class PlaylistViewSet(
|
|||
|
||||
|
||||
class PlaylistTrackViewSet(
|
||||
mixins.RetrieveModelMixin,
|
||||
mixins.CreateModelMixin,
|
||||
mixins.UpdateModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
mixins.ListModelMixin,
|
||||
viewsets.GenericViewSet):
|
||||
|
||||
serializer_class = serializers.PlaylistTrackSerializer
|
||||
queryset = (models.PlaylistTrack.objects.all())
|
||||
permission_classes = [ConditionalAuthentication]
|
||||
permission_classes = [
|
||||
permissions.ConditionalAuthentication,
|
||||
permissions.OwnerPermission,
|
||||
IsAuthenticatedOrReadOnly,
|
||||
]
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
serializer = serializers.PlaylistTrackCreateSerializer(
|
||||
data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
if serializer.validated_data['playlist'].user != request.user:
|
||||
return Response(
|
||||
{'playlist': [
|
||||
'This playlist does not exists or you do not have the'
|
||||
'permission to edit it']
|
||||
},
|
||||
status=400)
|
||||
instance = self.perform_create(serializer)
|
||||
serializer = self.get_serializer(instance=instance)
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||
|
||||
def get_queryset(self):
|
||||
return self.queryset.filter(playlist__user=self.request.user)
|
||||
return self.queryset.filter(
|
||||
fields.privacy_level_query(
|
||||
self.request.user,
|
||||
lookup_field='playlist__privacy_level'))
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import json
|
||||
import pytest
|
||||
|
||||
from django.urls import reverse
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils import timezone
|
||||
|
@ -48,3 +50,67 @@ def test_can_add_playlist_track_via_api(factories, logged_in_api_client):
|
|||
response = logged_in_api_client.post(url, data)
|
||||
plts = logged_in_api_client.user.playlists.latest('id').playlist_tracks.all()
|
||||
assert plts.first().track == tracks[0]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('name,method', [
|
||||
('api:v1:playlist-tracks-list', 'post'),
|
||||
('api:v1:playlists-list', 'post'),
|
||||
])
|
||||
def test_url_requires_login(name, method, factories, api_client):
|
||||
url = reverse(name)
|
||||
|
||||
response = getattr(api_client, method)(url, {})
|
||||
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
def test_only_can_add_track_on_own_playlist_via_api(
|
||||
factories, logged_in_api_client):
|
||||
track = factories['music.Track']()
|
||||
playlist = factories['playlists.Playlist']()
|
||||
url = reverse('api:v1:playlist-tracks-list')
|
||||
data = {
|
||||
'playlist': playlist.pk,
|
||||
'track': track.pk
|
||||
}
|
||||
|
||||
response = logged_in_api_client.post(url, data)
|
||||
assert response.status_code == 400
|
||||
assert playlist.playlist_tracks.count() == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize('level', ['instance', 'me', 'followers'])
|
||||
def test_playlist_privacy_respected_in_list_anon(level, factories, api_client):
|
||||
factories['playlists.Playlist'](privacy_level=level)
|
||||
url = reverse('api:v1:playlists-list')
|
||||
response = api_client.get(url)
|
||||
|
||||
assert response.data['count'] == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize('method', ['PUT', 'PATCH', 'DELETE'])
|
||||
def test_only_owner_can_edit_playlist(method, factories, api_client):
|
||||
playlist = factories['playlists.Playlist']()
|
||||
url = reverse('api:v1:playlists-detail', kwargs={'pk': playlist.pk})
|
||||
response = api_client.get(url)
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
@pytest.mark.parametrize('method', ['PUT', 'PATCH', 'DELETE'])
|
||||
def test_only_owner_can_edit_playlist_track(method, factories, api_client):
|
||||
plt = factories['playlists.PlaylistTrack']()
|
||||
url = reverse('api:v1:playlist-tracks-detail', kwargs={'pk': plt.pk})
|
||||
response = api_client.get(url)
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
@pytest.mark.parametrize('level', ['instance', 'me', 'followers'])
|
||||
def test_playlist_track_privacy_respected_in_list_anon(
|
||||
level, factories, api_client):
|
||||
factories['playlists.PlaylistTrack'](playlist__privacy_level=level)
|
||||
url = reverse('api:v1:playlist-tracks-list')
|
||||
response = api_client.get(url)
|
||||
|
||||
assert response.data['count'] == 0
|
||||
|
|
Loading…
Reference in New Issue