security: Hardened the HLS proxy change_stream endpoint by converting it from a plain Django view to a DRF @api_view with @permission_classes([IsAdmin]), ensuring the endpoint actually enforces admin-only access. The previous decorator arrangement (@csrf_exempt + @permission_classes) had no effect on a plain Django view.

This commit is contained in:
SergeantPanda 2026-04-09 19:58:40 -05:00
parent df6d821135
commit 7f64642003

View file

@ -4,6 +4,8 @@ import logging
from django.http import StreamingHttpResponse, JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from rest_framework.decorators import api_view, permission_classes
from apps.accounts.permissions import IsAdmin
from .server import ProxyServer, Config
logger = logging.getLogger(__name__)
@ -15,7 +17,7 @@ def stream_endpoint(request, channel_id):
"""Handle HLS manifest requests"""
if channel_id not in proxy_server.stream_managers:
return JsonResponse({'error': 'Channel not found'}, status=404)
response = proxy_server.stream_endpoint(channel_id)
return StreamingHttpResponse(
response[0],
@ -30,10 +32,10 @@ def get_segment(request, segment_name):
try:
segment_num = int(segment_name.split('.')[0])
buffer = proxy_server.stream_buffers.get(segment_num)
if not buffer:
return JsonResponse({'error': 'Segment not found'}, status=404)
return StreamingHttpResponse(
buffer,
content_type='video/MP2T'
@ -44,19 +46,19 @@ def get_segment(request, segment_name):
logger.error(f"Error serving segment: {e}")
return JsonResponse({'error': str(e)}, status=500)
@csrf_exempt
@require_http_methods(["POST"])
@api_view(["POST"])
@permission_classes([IsAdmin])
def change_stream(request, channel_id):
"""Change stream URL for existing channel"""
try:
if channel_id not in proxy_server.stream_managers:
return JsonResponse({'error': 'Channel not found'}, status=404)
data = json.loads(request.body)
new_url = data.get('url')
if not new_url:
return JsonResponse({'error': 'No URL provided'}, status=400)
manager = proxy_server.stream_managers[channel_id]
if manager.update_url(new_url):
return JsonResponse({
@ -64,7 +66,7 @@ def change_stream(request, channel_id):
'channel': channel_id,
'url': new_url
})
return JsonResponse({
'message': 'URL unchanged',
'channel': channel_id,
@ -85,7 +87,7 @@ def initialize_stream(request, channel_id):
url = data.get('url')
if not url:
return JsonResponse({'error': 'No URL provided'}, status=400)
proxy_server.initialize_channel(url, channel_id)
return JsonResponse({
'message': 'Stream initialized',