- Add Django Channels 4 + channels-redis to requirements and INSTALLED_APPS
- Upgrade ASGI config to ProtocolTypeRouter with JWT-authenticated WebSocket routing
- Add JWTAuthMiddleware for WebSocket token auth via query param
- Add CallSession, CallParticipant, CallEvent models with migration 0004
- MeetingCallConsumer: join/leave, P2P SDP/ICE relay via per-user groups,
instructor mute/unmute/kick with DB audit and WS broadcast
- REST endpoints: GET/POST/DELETE /meetings/{id}/call/ (session lifecycle),
POST /moderate/ (mute/unmute/kick), POST /screen-share/, GET /events/ (audit log)
- IsMeetingModerator permission (accepts training:signoff or meeting:moderate)
- Services: get_or_create_call_session, end_call_session, apply_moderation_action,
toggle_screen_share with full CallEvent audit trail
- Integration tests covering REST lifecycle, moderation, and WebSocket signaling
Co-Authored-By: Paperclip <noreply@paperclip.ing>
38 lines
1.9 KiB
Python
38 lines
1.9 KiB
Python
from django.urls import path
|
|
|
|
from .views import (
|
|
EmployeeAttendanceListView,
|
|
MarkInProgressView,
|
|
MarkOnlinePassedView,
|
|
MeetingAttendanceView,
|
|
MeetingCallEventsView,
|
|
MeetingCallModerationView,
|
|
MeetingCallScreenShareView,
|
|
MeetingCallSessionView,
|
|
MeetingDetailView,
|
|
MeetingListCreateView,
|
|
MeetingParticipantsCreateView,
|
|
PendingSignoffListView,
|
|
TrainerSignoffView,
|
|
TrainingRecordDetailView,
|
|
)
|
|
|
|
app_name = "training"
|
|
|
|
urlpatterns = [
|
|
path("records/<uuid:record_id>/", TrainingRecordDetailView.as_view(), name="record-detail"),
|
|
path("records/<uuid:record_id>/start/", MarkInProgressView.as_view(), name="mark-in-progress"),
|
|
path("records/<uuid:record_id>/online-passed/", MarkOnlinePassedView.as_view(), name="mark-online-passed"),
|
|
path("records/<uuid:record_id>/signoff/", TrainerSignoffView.as_view(), name="trainer-signoff"),
|
|
path("pending-signoff/", PendingSignoffListView.as_view(), name="pending-signoff"),
|
|
path("meetings/", MeetingListCreateView.as_view(), name="meeting-list-create"),
|
|
path("meetings/<uuid:meeting_id>/", MeetingDetailView.as_view(), name="meeting-detail"),
|
|
path("meetings/<uuid:meeting_id>/participants/", MeetingParticipantsCreateView.as_view(), name="meeting-participants-create"),
|
|
path("meetings/<uuid:meeting_id>/attendance/", MeetingAttendanceView.as_view(), name="meeting-attendance"),
|
|
path("attendance/", EmployeeAttendanceListView.as_view(), name="employee-attendance-list"),
|
|
path("meetings/<uuid:meeting_id>/call/", MeetingCallSessionView.as_view(), name="meeting-call-session"),
|
|
path("meetings/<uuid:meeting_id>/call/moderate/", MeetingCallModerationView.as_view(), name="meeting-call-moderate"),
|
|
path("meetings/<uuid:meeting_id>/call/screen-share/", MeetingCallScreenShareView.as_view(), name="meeting-call-screen-share"),
|
|
path("meetings/<uuid:meeting_id>/call/events/", MeetingCallEventsView.as_view(), name="meeting-call-events"),
|
|
]
|