Files

68 lines
3.1 KiB
Python

from rest_framework import decorators, mixins, permissions, response, status, views, viewsets
from apps.core.errors import error_response
from apps.core.settings_service import SettingsService
from apps.live_monitoring.models import Camera
from apps.live_monitoring.serializers import CameraSerializer
from apps.live_monitoring.services import StreamAccessService
from apps.rbac.permissions import ActionPermission
class CameraViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
queryset = Camera.objects.filter(active=True)
serializer_class = CameraSerializer
permission_classes = [ActionPermission]
code_map = {"list": "processing.view", "retrieve": "processing.view", "access": "processing.view"}
def list(self, request, *args, **kwargs):
if not SettingsService().get_bool("camera.enabled", True):
return response.Response({"count": 0, "next": None, "previous": None, "results": []})
return super().list(request, *args, **kwargs)
@decorators.action(detail=True, methods=["post"])
def access(self, request, pk=None):
if not SettingsService().get_bool("camera.enabled", True):
return response.Response(
error_response("MONITORING_DISABLED", "Live monitoring is disabled."),
status=status.HTTP_403_FORBIDDEN,
)
camera = self.get_object()
service = StreamAccessService()
if not service.can_access(request.user, camera):
return response.Response(
error_response("STREAM_FORBIDDEN", "You do not have access to this stream."),
status=status.HTTP_403_FORBIDDEN,
)
token, expires_at = service.issue_token(camera)
access_url = request.build_absolute_uri(f"/api/v1/live-monitoring/streams/verify/?token={token}")
return response.Response({"token": token, "expires_at": expires_at, "access_url": access_url})
class VerifyStreamView(views.APIView):
permission_classes = [permissions.AllowAny]
def get(self, request):
if not SettingsService().get_bool("camera.enabled", True):
return response.Response(
error_response("MONITORING_DISABLED", "Live monitoring is disabled."),
status=status.HTTP_403_FORBIDDEN,
)
token = request.query_params.get("token")
service = StreamAccessService()
payload = service.verify_token(token)
if not payload:
return response.Response(
error_response("INVALID_TOKEN", "Invalid or expired stream token."),
status=status.HTTP_403_FORBIDDEN,
)
try:
camera = Camera.objects.get(pk=payload["camera"], active=True)
except Camera.DoesNotExist:
return response.Response(
error_response("CAMERA_NOT_FOUND", "Camera not found."),
status=status.HTTP_404_NOT_FOUND,
)
stream = service.resolve_stream(camera)
# Keep ``url`` alias for older clients; ``stream_url`` is canonical.
return response.Response({**stream, "url": stream.get("stream_url")})