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

Additional permissions checks on playlist views

parent 4f7fa09a
No related branches found
No related tags found
No related merge requests found
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'))
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
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