Browse Source

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.
master
Mohsen Taba 4 months ago
parent
commit
344083bcab
  1. 85
      apps/course/views/live_session.py

85
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.serializers import LiveSessionRoomCreateSerializer, LiveSessionTokenSerializer, LiveSessionRecordedFileSerializer, LiveSessionRecordingSerializer
from apps.course.services.plugnmeet import PlugNMeetClient, PlugNMeetError from apps.course.services.plugnmeet import PlugNMeetClient, PlugNMeetError
from utils.exceptions import AppAPIException from utils.exceptions import AppAPIException
from django.conf import settings
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -45,69 +45,70 @@ class CourseLiveSessionRoomCreateAPIView(GenericAPIView):
) )
def post(self, request, slug, *args, **kwargs): def post(self, request, slug, *args, **kwargs):
# 1. Validation and Permission Logic
# 1. Standard Permissions Logic
course = get_object_or_404(Course, slug=slug) course = get_object_or_404(Course, slug=slug)
if not request.user.can_manage_course(course): 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)
# 2. Setup ID and Metadata
room_id = f"room-{course.id}-imamjavad" room_id = f"room-{course.id}-imamjavad"
subject = f"{course.title} Live Session" subject = f"{course.title} Live Session"
metadata = self._build_metadata(subject) metadata = self._build_metadata(subject)
# 3. Create Room via PlugNMeet API
# 3. Use your CLEAN PlugNMeetClient
try: 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({ plugnmeet_response = client.create_room({
'room_id': room_id, 'room_id': room_id,
'metadata': metadata, '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: except Exception as exc:
logger.error(f"PlugNMeet Error: {exc}") logger.error(f"PlugNMeet Error: {exc}")
raise AppAPIException({'message': str(exc)}, status_code=500) raise AppAPIException({'message': str(exc)}, status_code=500)
# 4. Save to Database
# 5. Database Logic
session, created = CourseLiveSession.objects.get_or_create( 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({ return Response({
'success': True, '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): # def post(self, request, slug, *args, **kwargs):
# logger.info(f"[LiveSession Create] Request from user_id={request.user.id} for course={slug}") # logger.info(f"[LiveSession Create] Request from user_id={request.user.id} for course={slug}")

Loading…
Cancel
Save