From 26e35a63a0d0cef45d3572afe14584597b477249 Mon Sep 17 00:00:00 2001 From: Zachary Hancock Date: Fri, 3 Nov 2023 15:28:51 -0400 Subject: [PATCH] feat: roster endpoint POC (#208) * feat: roster endpoint POC * fix: missing test setting * test: fixup failing test * style: nocover temp changes --- edx_exams/apps/lti/tests/test_views.py | 3 +++ edx_exams/apps/lti/urls.py | 1 + edx_exams/apps/lti/views.py | 36 ++++++++++++++++++++++++++ edx_exams/settings/local.py | 1 + edx_exams/settings/test.py | 1 + 5 files changed, 42 insertions(+) diff --git a/edx_exams/apps/lti/tests/test_views.py b/edx_exams/apps/lti/tests/test_views.py index 7cbf675d..80d5eeb9 100644 --- a/edx_exams/apps/lti/tests/test_views.py +++ b/edx_exams/apps/lti/tests/test_views.py @@ -640,6 +640,9 @@ def test_lti_launch(self, mock_create_launch_url): resource_link_id=self.exam.resource_id, external_user_id=str(self.course_staff_user.anonymous_user_id), context_id=self.exam.course_id, + custom_parameters={ + 'roster_url': 'http://test.exams:18740/lti/exam/1/instructor_tool/roster', + } ) ) self.assertEqual(response.status_code, 302) diff --git a/edx_exams/apps/lti/urls.py b/edx_exams/apps/lti/urls.py index 42a59b91..9c39053d 100644 --- a/edx_exams/apps/lti/urls.py +++ b/edx_exams/apps/lti/urls.py @@ -12,4 +12,5 @@ path('end_assessment/', views.end_assessment, name='end_assessment'), path('start_proctoring/', views.start_proctoring, name='start_proctoring'), path('exam//instructor_tool', views.launch_instructor_tool, name='instructor_tool'), + path('exam//instructor_tool/roster', views.exam_roster, name='exam_roster'), ] diff --git a/edx_exams/apps/lti/views.py b/edx_exams/apps/lti/views.py index 7742e0a9..b525dedb 100644 --- a/edx_exams/apps/lti/views.py +++ b/edx_exams/apps/lti/views.py @@ -7,9 +7,12 @@ from decimal import Decimal from urllib.parse import urljoin +from django.conf import settings from django.contrib.auth import login +from django.http import JsonResponse from django.shortcuts import redirect from django.urls import reverse +from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication from lti_consumer.api import get_end_assessment_return, get_lti_1p3_launch_start_url @@ -25,6 +28,7 @@ from edx_exams.apps.core.api import ( get_attempt_by_id, get_attempt_for_user_with_attempt_number_and_resource_id, + get_exam_attempts, get_exam_by_id, get_exam_url_path, update_attempt_status @@ -360,6 +364,38 @@ def launch_instructor_tool(request, exam_id): resource_link_id=exam.resource_id, external_user_id=str(user.anonymous_user_id), context_id=exam.course_id, + custom_parameters={ + 'roster_url': settings.LTI_API_BASE + reverse('lti:exam_roster', kwargs={'exam_id': exam.id}), + } ) + # user is authenticated via JWT so use that to create a + # session with this service's authentication backend + request.user.backend = EDX_OAUTH_BACKEND + login(request, user) + return redirect(get_lti_1p3_launch_start_url(launch_data)) + + +@csrf_exempt +@require_http_methods(['GET']) +def exam_roster(request, exam_id): + # pragma: no cover + """ + Temporary endpoint to prove we can authenticate this request properly + """ + user = request.user + exam = get_exam_by_id(exam_id) + if not user.is_staff and not user.has_course_staff_permission(exam.course_id): + return Response(status=status.HTTP_403_FORBIDDEN) + + attempts = get_exam_attempts(exam_id) + attempts.select_related('user') + + users = set(attempt.user for attempt in attempts) + roster = [ + (user.anonymous_user_id, user.username) + for user in users + ] + + return JsonResponse(roster, safe=False) diff --git a/edx_exams/settings/local.py b/edx_exams/settings/local.py index 5a752b68..ba38c9a9 100644 --- a/edx_exams/settings/local.py +++ b/edx_exams/settings/local.py @@ -118,6 +118,7 @@ SESSION_COOKIE_DOMAIN = 'localhost' ROOT_URL = 'http://localhost:18740' +LTI_API_BASE = 'http://localhost:18740' LMS_ROOT_URL = 'http://localhost:18000' LEARNING_MICROFRONTEND_URL = 'http://localhost:2000' EXAMS_DASHBOARD_MFE_URL = 'http://localhost:2020' diff --git a/edx_exams/settings/test.py b/edx_exams/settings/test.py index 01c0084a..633c37dd 100644 --- a/edx_exams/settings/test.py +++ b/edx_exams/settings/test.py @@ -23,6 +23,7 @@ ) ROOT_URL = 'http://test.exams:18740' +LTI_API_BASE = 'http://test.exams:18740' LMS_ROOT_URL = 'http://test.lms:18000' LEARNING_MICROFRONTEND_URL = 'http://test.learning:2000'