diff --git a/api/config/settings/common.py b/api/config/settings/common.py index 13624511c21b2c681cf233d49cdd93903bd9917d..3000feddba0ee07e93fc4d54caac0b5d8fd66ee1 100644 --- a/api/config/settings/common.py +++ b/api/config/settings/common.py @@ -536,11 +536,11 @@ REST_FRAMEWORK = { ), "DEFAULT_AUTHENTICATION_CLASSES": ( "oauth2_provider.contrib.rest_framework.OAuth2Authentication", - "rest_framework.authentication.SessionAuthentication", "funkwhale_api.common.authentication.JSONWebTokenAuthenticationQS", "funkwhale_api.common.authentication.BearerTokenHeaderAuth", "funkwhale_api.common.authentication.JSONWebTokenAuthentication", "rest_framework.authentication.BasicAuthentication", + "rest_framework.authentication.SessionAuthentication", ), "DEFAULT_PERMISSION_CLASSES": ( "funkwhale_api.users.oauth.permissions.ScopePermission", diff --git a/api/funkwhale_api/common/permissions.py b/api/funkwhale_api/common/permissions.py index 4ab405eb47c224231c8526c7c0c025c74089999f..237fc4ae4141813e505c98df76d2b0ea165ea7cb 100644 --- a/api/funkwhale_api/common/permissions.py +++ b/api/funkwhale_api/common/permissions.py @@ -47,6 +47,6 @@ class OwnerPermission(BasePermission): owner_field = getattr(view, "owner_field", "user") owner = operator.attrgetter(owner_field)(obj) - if owner != request.user: + if not owner or not request.user.is_authenticated or owner != request.user: raise Http404 return True diff --git a/api/funkwhale_api/radios/radios.py b/api/funkwhale_api/radios/radios.py index f19c6b884d299fd53c17b472cc8324f7beb69d97..a0dc36b62adf8d76eb4c65f472ec04f440f56fc2 100644 --- a/api/funkwhale_api/radios/radios.py +++ b/api/funkwhale_api/radios/radios.py @@ -47,6 +47,8 @@ class SessionRadio(SimpleRadio): qs = Track.objects.all() if not self.session: return qs + if not self.session.user: + return qs query = moderation_filters.get_filtered_content_query( config=moderation_filters.USER_FILTER_CONFIG["TRACK"], user=self.session.user, @@ -62,7 +64,9 @@ class SessionRadio(SimpleRadio): if self.session: queryset = self.filter_from_session(queryset) if kwargs.pop("filter_playable", True): - queryset = queryset.playable_by(self.session.user.actor) + queryset = queryset.playable_by( + self.session.user.actor if self.session.user else None + ) queryset = self.filter_queryset(queryset) return queryset @@ -129,7 +133,7 @@ class CustomRadio(SessionRadio): try: user = data["user"] except KeyError: - user = context["user"] + user = context.get("user") try: assert data["custom_radio"].user == user or data["custom_radio"].is_public except KeyError: diff --git a/api/funkwhale_api/radios/serializers.py b/api/funkwhale_api/radios/serializers.py index 9bffbf5b9cd3ce0c04100dcf3a68de008964b416..397452ecc0e5c6646a82ea663fdc6bb099e2f803 100644 --- a/api/funkwhale_api/radios/serializers.py +++ b/api/funkwhale_api/radios/serializers.py @@ -70,7 +70,7 @@ class RadioSessionSerializer(serializers.ModelSerializer): return data def create(self, validated_data): - validated_data["user"] = self.context["user"] + validated_data["user"] = self.context.get("user") if validated_data.get("related_object_id"): radio = registry[validated_data["radio_type"]]() validated_data["related_object"] = radio.get_related_object( diff --git a/api/funkwhale_api/radios/views.py b/api/funkwhale_api/radios/views.py index fa0a6fe4a6037aa59a6fb0800f63760e82ba78f0..0a5f1cd6cfa282c17aa472db1d6d5ce04779487a 100644 --- a/api/funkwhale_api/radios/views.py +++ b/api/funkwhale_api/radios/views.py @@ -1,5 +1,5 @@ from django.db.models import Q -from rest_framework import mixins, permissions, status, viewsets +from rest_framework import mixins, status, viewsets from rest_framework.decorators import action from rest_framework.response import Response @@ -28,6 +28,7 @@ class RadioViewSet( required_scope = "radios" owner_field = "user" owner_checks = ["write"] + anonymous_policy = "setting" def get_queryset(self): queryset = models.Radio.objects.all() @@ -82,11 +83,30 @@ class RadioSessionViewSet( serializer_class = serializers.RadioSessionSerializer queryset = models.RadioSession.objects.all() - permission_classes = [permissions.IsAuthenticated] + permission_classes = [] def get_queryset(self): queryset = super().get_queryset() - return queryset.filter(user=self.request.user) + if self.request.user.is_authenticated: + return queryset.filter( + Q(user=self.request.user) + | Q(session_key=self.request.session.session_key) + ) + + return queryset.filter(session_key=self.request.session.session_key).exclude( + session_key=None + ) + + def perform_create(self, serializer): + if ( + not self.request.user.is_authenticated + and not self.request.session.session_key + ): + self.request.session.create() + return serializer.save( + user=self.request.user if self.request.user.is_authenticated else None, + session_key=self.request.session.session_key, + ) def get_serializer_context(self): context = super().get_serializer_context() @@ -97,14 +117,19 @@ class RadioSessionViewSet( class RadioSessionTrackViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet): serializer_class = serializers.RadioSessionTrackSerializer queryset = models.RadioSessionTrack.objects.all() - permission_classes = [permissions.IsAuthenticated] + permission_classes = [] def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) session = serializer.validated_data["session"] + if not request.user.is_authenticated and not request.session.session_key: + self.request.session.create() try: - assert request.user == session.user + assert (request.user == session.user) or ( + request.session.session_key == session.session_key + and session.session_key + ) except AssertionError: return Response(status=status.HTTP_403_FORBIDDEN) session.radio.pick() diff --git a/changes/changelog.d/563.bugfix b/changes/changelog.d/563.bugfix new file mode 100644 index 0000000000000000000000000000000000000000..14f49b75e7a714b70554ba7a16b1e570b78fc9cc --- /dev/null +++ b/changes/changelog.d/563.bugfix @@ -0,0 +1 @@ +Fixed unplayable radios for anonymous users (#563) diff --git a/front/src/components/library/Radios.vue b/front/src/components/library/Radios.vue index 68eb11f0b1dd835119577d5c74ceb49eaaa83796..9b2f7bf82010bc1eed389ca072468a5c51c62ff0 100644 --- a/front/src/components/library/Radios.vue +++ b/front/src/components/library/Radios.vue @@ -10,9 +10,9 @@ <translate translate-context="Content/Radio/Title">Instance radios</translate> </h3> <div class="ui cards"> - <radio-card :type="'favorites'"></radio-card> + <radio-card v-if="$store.state.auth.authenticated" :type="'favorites'"></radio-card> <radio-card :type="'random'"></radio-card> - <radio-card :type="'less-listened'"></radio-card> + <radio-card v-if="$store.state.auth.authenticated" :type="'less-listened'"></radio-card> </div> </div> diff --git a/front/src/store/auth.js b/front/src/store/auth.js index 29c4c5d719da539922c36f71a3996b2101ed180b..52cc98a6de7abde1ebfb1c03bd5ea434e1fa2af8 100644 --- a/front/src/store/auth.js +++ b/front/src/store/auth.js @@ -118,10 +118,6 @@ export default { } }, fetchProfile ({commit, dispatch, state}) { - if (document) { - // this is to ensure we do not have any leaking cookie set by django - document.cookie = 'sessionid=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;' - } return new Promise((resolve, reject) => { axios.get('users/users/me/').then((response) => {