mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-18 00:55:50 +00:00
security: proxy streaming endpoints (stream_ts, stream_xc, stream_vod, head_vod, stream_xc_movie, stream_xc_episode) use @permission_classes([AllowAny]) (access is controlled by the per-stream-type network allow-list inside the view body); the UserAgentViewSet, StreamProfileViewSet, CoreSettingsViewSet, and ProxySettingsViewSet gained get_permissions() methods mapping read actions to IsStandardUser and write actions to IsAdmin; and AuthViewSet.logout was updated to return [Authenticated()].
This commit is contained in:
parent
66ee67da30
commit
fa9a7868ff
4 changed files with 35 additions and 2 deletions
|
|
@ -159,8 +159,7 @@ class AuthViewSet(viewsets.ViewSet):
|
|||
Login doesn't require auth, but logout does
|
||||
"""
|
||||
if self.action == 'logout':
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
return [IsAuthenticated()]
|
||||
return [Authenticated()]
|
||||
return []
|
||||
|
||||
@extend_schema(
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ from apps.m3u.models import M3UAccount, M3UAccountProfile
|
|||
from apps.accounts.models import User
|
||||
from core.models import UserAgent, CoreSettings, PROXY_PROFILE_NAME
|
||||
from rest_framework.decorators import api_view, permission_classes
|
||||
from rest_framework.permissions import AllowAny
|
||||
from rest_framework.response import Response
|
||||
from apps.accounts.permissions import (
|
||||
IsAdmin,
|
||||
|
|
@ -46,6 +47,7 @@ logger = get_logger()
|
|||
|
||||
|
||||
@api_view(["GET"])
|
||||
@permission_classes([AllowAny])
|
||||
def stream_ts(request, channel_id, user=None):
|
||||
if not network_access_allowed(request, "STREAMS"):
|
||||
return JsonResponse({"error": "Forbidden"}, status=403)
|
||||
|
|
@ -554,6 +556,7 @@ def stream_ts(request, channel_id, user=None):
|
|||
|
||||
|
||||
@api_view(["GET"])
|
||||
@permission_classes([AllowAny])
|
||||
def stream_xc(request, username, password, channel_id):
|
||||
user = get_object_or_404(User, username=username)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from apps.m3u.models import M3UAccountProfile
|
|||
from apps.proxy.vod_proxy.multi_worker_connection_manager import MultiWorkerVODConnectionManager, infer_content_type_from_url, get_vod_client_stop_key
|
||||
from .utils import get_client_info
|
||||
from rest_framework.decorators import api_view, permission_classes
|
||||
from rest_framework.permissions import AllowAny
|
||||
from apps.accounts.models import User
|
||||
from apps.accounts.permissions import IsAdmin
|
||||
from apps.proxy.utils import check_user_stream_limits
|
||||
|
|
@ -291,6 +292,7 @@ def _transform_url(original_url, m3u_profile):
|
|||
return original_url
|
||||
|
||||
@api_view(["GET"])
|
||||
@permission_classes([AllowAny])
|
||||
def stream_vod(request, content_type, content_id, session_id=None, profile_id=None, user=None):
|
||||
"""
|
||||
Stream VOD content (movies or series episodes) with session-based connection reuse
|
||||
|
|
@ -500,6 +502,7 @@ def stream_vod(request, content_type, content_id, session_id=None, profile_id=No
|
|||
return HttpResponse(f"Streaming error: {str(e)}", status=500)
|
||||
|
||||
@api_view(["HEAD"])
|
||||
@permission_classes([AllowAny])
|
||||
def head_vod(request, content_type, content_id, session_id=None, profile_id=None):
|
||||
"""
|
||||
Handle HEAD requests for FUSE filesystem integration
|
||||
|
|
@ -987,6 +990,7 @@ def stop_vod_client(request):
|
|||
return JsonResponse({'error': str(e)}, status=500)
|
||||
|
||||
@api_view(["GET"])
|
||||
@permission_classes([AllowAny])
|
||||
def stream_xc_movie(request, username, password, stream_id, extension):
|
||||
from apps.vod.models import M3UMovieRelation
|
||||
|
||||
|
|
@ -1017,6 +1021,7 @@ def stream_xc_movie(request, username, password, stream_id, extension):
|
|||
return stream_vod(request._request, 'movie', movie_relation.movie.uuid, session_id, profile_id, user)
|
||||
|
||||
@api_view(["GET"])
|
||||
@permission_classes([AllowAny])
|
||||
def stream_xc_episode(request, username, password, stream_id, extension):
|
||||
from apps.vod.models import M3UEpisodeRelation
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ import os
|
|||
from core.tasks import rehash_streams
|
||||
from apps.accounts.permissions import (
|
||||
Authenticated,
|
||||
IsAdmin,
|
||||
IsStandardUser,
|
||||
permission_classes_by_action,
|
||||
)
|
||||
from dispatcharr.utils import get_client_ip
|
||||
|
||||
|
|
@ -50,6 +53,12 @@ class UserAgentViewSet(viewsets.ModelViewSet):
|
|||
queryset = UserAgent.objects.all()
|
||||
serializer_class = UserAgentSerializer
|
||||
|
||||
def get_permissions(self):
|
||||
try:
|
||||
return [perm() for perm in permission_classes_by_action[self.action]]
|
||||
except KeyError:
|
||||
return [Authenticated()]
|
||||
|
||||
|
||||
class StreamProfileViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
|
|
@ -59,6 +68,12 @@ class StreamProfileViewSet(viewsets.ModelViewSet):
|
|||
queryset = StreamProfile.objects.all()
|
||||
serializer_class = StreamProfileSerializer
|
||||
|
||||
def get_permissions(self):
|
||||
try:
|
||||
return [perm() for perm in permission_classes_by_action[self.action]]
|
||||
except KeyError:
|
||||
return [Authenticated()]
|
||||
|
||||
|
||||
class CoreSettingsViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
|
|
@ -69,6 +84,12 @@ class CoreSettingsViewSet(viewsets.ModelViewSet):
|
|||
queryset = CoreSettings.objects.all()
|
||||
serializer_class = CoreSettingsSerializer
|
||||
|
||||
def get_permissions(self):
|
||||
try:
|
||||
return [perm() for perm in permission_classes_by_action[self.action]]
|
||||
except KeyError:
|
||||
return [Authenticated()]
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
old_value = instance.value
|
||||
|
|
@ -171,6 +192,11 @@ class ProxySettingsViewSet(viewsets.ViewSet):
|
|||
"""
|
||||
serializer_class = ProxySettingsSerializer
|
||||
|
||||
def get_permissions(self):
|
||||
if self.action in ('list', 'retrieve'):
|
||||
return [IsStandardUser()]
|
||||
return [IsAdmin()]
|
||||
|
||||
def _get_or_create_settings(self):
|
||||
"""Get or create the proxy settings CoreSettings entry"""
|
||||
try:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue