From 344083bcab0ac7e840aec7f9eb1f419ecf11324c Mon Sep 17 00:00:00 2001 From: mohsentaba Date: Sun, 1 Feb 2026 15:04:19 +0330 Subject: [PATCH] Refactor CourseLiveSessionRoomCreateAPIView to streamline live session creation - Updated permission logic for course management. - Simplified room ID setup and metadata handling. - Enhanced PlugNMeetClient integration for room creation and token generation. - Improved error handling and logging for API interactions. - Adjusted response structure to include the generated access token for frontend use. --- apps/course/views/live_session.py | 87 ++++++++++++++++--------------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/apps/course/views/live_session.py b/apps/course/views/live_session.py index 3f45c9d..727640e 100644 --- a/apps/course/views/live_session.py +++ b/apps/course/views/live_session.py @@ -17,7 +17,7 @@ from apps.course.models import Course, CourseLiveSession, Participant, LiveSessi from apps.course.serializers import LiveSessionRoomCreateSerializer, LiveSessionTokenSerializer, LiveSessionRecordedFileSerializer, LiveSessionRecordingSerializer from apps.course.services.plugnmeet import PlugNMeetClient, PlugNMeetError from utils.exceptions import AppAPIException - +from django.conf import settings logger = logging.getLogger(__name__) @@ -45,69 +45,70 @@ class CourseLiveSessionRoomCreateAPIView(GenericAPIView): ) def post(self, request, slug, *args, **kwargs): - # 1. Validation and Permission Logic + # 1. Standard Permissions Logic course = get_object_or_404(Course, slug=slug) if not request.user.can_manage_course(course): - raise AppAPIException({'message': 'Permission denied'}, status_code=status.HTTP_403_FORBIDDEN) + raise AppAPIException({'message': 'Permission denied'}, status_code=403) - # 2. Build Safe Room ID (Prefix with 'room-' to satisfy NATS rules) - # OLD: f"{course.id}-imamjavad" -> "9-imamjavad" (Risk of NATS errors) - # NEW: f"room-{course.id}-imamjavad" -> "room-9-imamjavad" (Safe) - room_id = f"room-{course.id}-imamjavad" - + # 2. Setup ID and Metadata + room_id = f"room-{course.id}-imamjavad" subject = f"{course.title} Live Session" metadata = self._build_metadata(subject) - # 3. Create Room via PlugNMeet API + # 3. Use your CLEAN PlugNMeetClient try: - client = PlugNMeetClient() + client = PlugNMeetClient() # Loads keys from settings automatically - # Note: client.create_room only CREATES the room. - # It does not give you a token to join it. + # This uses the keys internally to talk to the server plugnmeet_response = client.create_room({ 'room_id': room_id, 'metadata': metadata, }) + + # 4. Generate the JOIN TOKEN (The Entry Ticket) + # Users CANNOT enter without this. + token_payload = { + "room_id": room_id, + "user_info": { + "name": f"{request.user.first_name} {request.user.last_name}", + "user_id": str(request.user.id), + "is_admin": True, + "is_hidden": False + } + } + + # Check if your client has a method for this, otherwise use manual: + # access_token = client.get_join_token(token_payload) + # If not, we do it manually here using the SAME secret from settings: + + pnm_token = jwt.encode( + { + "iss": settings.PLUGNMEET_API_KEY, + "exp": int(time.time()) + 3600, + "sub": str(request.user.id), + **token_payload + }, + settings.PLUGNMEET_API_SECRET, + algorithm="HS256" + ) + except Exception as exc: logger.error(f"PlugNMeet Error: {exc}") raise AppAPIException({'message': str(exc)}, status_code=500) - # 4. Save to Database + # 5. Database Logic session, created = CourseLiveSession.objects.get_or_create( - course=course, - room_id=room_id, - defaults={'subject': subject, 'started_at': timezone.now()}, + course=course, room_id=room_id, + defaults={'subject': subject, 'started_at': timezone.now()} ) - # 5. GENERATE JOIN TOKEN (Critical for User Access) - # You must fetch these exactly as they are in your config.yaml - PNM_API_KEY = "habibmeet_api_key_2024" - PNM_SECRET = "habibmeet_secret_zumyyYWqv7KR2kUqvYdq4z4sXg7XTBD2ljT6_2024" - - token_payload = { - "iss": PNM_API_KEY, # Issuer must be the API Key - "exp": int(time.time()) + 3600, # 1 hour expiry - "sub": str(request.user.id), - "room_id": room_id, - "name": f"{request.user.first_name} {request.user.last_name}", - "is_admin": True, # Gives moderator privileges - "user_id": str(request.user.id), - } - - # SIGN with the SECRET, not the key - token = jwt.encode(token_payload, PNM_SECRET, algorithm="HS256") - return Response({ 'success': True, - 'session': { - 'id': session.id, - 'room_id': session.room_id, - 'started_at': session.started_at, - }, - # Frontend uses this to connect: - # https://meet.newhorizonco.uk/?access_token={access_token} - 'access_token': token - }, status=status.HTTP_201_CREATED) + 'session': {'id': session.id, 'room_id': session.room_id}, + 'access_token': pnm_token # <--- REQUIRED for frontend + }, status=201) + + # def post(self, request, slug, *args, **kwargs): # logger.info(f"[LiveSession Create] Request from user_id={request.user.id} for course={slug}")