diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index 45c460d32908..cae166e7b9be 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -108,7 +108,7 @@ from lms.djangoapps.instructor_task.models import ReportStore from lms.djangoapps.instructor.views.serializer import ( AccessSerializer, BlockDueDateSerializer, RoleNameSerializer, ShowStudentExtensionSerializer, UserSerializer, - SendEmailSerializer, StudentAttemptsSerializer, ListInstructorTaskInputSerializer + SendEmailSerializer, StudentAttemptsSerializer, ListInstructorTaskInputSerializer, UniqueStudentIdentifierSerializer ) from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.course_groups.cohorts import add_user_to_cohort, is_course_cohorted @@ -1703,60 +1703,55 @@ def post(self, request, course_id): return JsonResponse({"status": success_status}) -@require_POST -@ensure_csrf_cookie -@cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_course_permission(permissions.VIEW_ENROLLMENTS) -@require_post_params( - unique_student_identifier="email or username of student for whom to get enrollment status" -) -def get_student_enrollment_status(request, course_id): +@method_decorator(cache_control(no_cache=True, no_store=True, must_revalidate=True), name='dispatch') +class GetStudentEnrollmentStatus(APIView): """ Get the enrollment status of a student. - Limited to staff access. - - Takes query parameter unique_student_identifier """ + permission_classes = (IsAuthenticated, permissions.InstructorPermission) + permission_name = permissions.VIEW_ENROLLMENTS - error = '' - user = None - mode = None - is_active = None + @method_decorator(ensure_csrf_cookie) + def post(self, request, course_id): + """ + Permission: Limited to staff access. + Takes query parameter unique_student_identifier + """ + error = '' + mode = None + is_active = None - course_id = CourseKey.from_string(course_id) - unique_student_identifier = request.POST.get('unique_student_identifier') + course_id = CourseKey.from_string(course_id) + unique_student_identifier = request.data.get("unique_student_identifier") - try: - user = get_student_from_identifier(unique_student_identifier) - mode, is_active = CourseEnrollment.enrollment_mode_for_user(user, course_id) - except User.DoesNotExist: - # The student could have been invited to enroll without having - # registered. We'll also look at CourseEnrollmentAllowed - # records, so let the lack of a User slide. - pass - - enrollment_status = _('Enrollment status for {student}: unknown').format(student=unique_student_identifier) - - if user and mode: - if is_active: - enrollment_status = _('Enrollment status for {student}: active').format(student=user) - else: - enrollment_status = _('Enrollment status for {student}: inactive').format(student=user) - else: - email = user.email if user else unique_student_identifier - allowed = CourseEnrollmentAllowed.may_enroll_and_unenrolled(course_id) - if allowed and email in [cea.email for cea in allowed]: - enrollment_status = _('Enrollment status for {student}: pending').format(student=email) + serializer_data = UniqueStudentIdentifierSerializer(data=request.data) + if not serializer_data.is_valid(): + return HttpResponseBadRequest(reason=serializer_data.errors) + + user = serializer_data.validated_data.get('unique_student_identifier') + if user: + mode, is_active = CourseEnrollment.enrollment_mode_for_user(user, course_id) + + if user and mode: + if is_active: + enrollment_status = _('Enrollment status for {student}: active').format(student=user) + else: + enrollment_status = _('Enrollment status for {student}: inactive').format(student=user) else: - enrollment_status = _('Enrollment status for {student}: never enrolled').format(student=email) + email = user.email if user else unique_student_identifier + allowed = CourseEnrollmentAllowed.may_enroll_and_unenrolled(course_id) + if allowed and email in [cea.email for cea in allowed]: + enrollment_status = _('Enrollment status for {student}: pending').format(student=email) + else: + enrollment_status = _('Enrollment status for {student}: never enrolled').format(student=email) - response_payload = { - 'course_id': str(course_id), - 'error': error, - 'enrollment_status': enrollment_status - } + response_payload = { + 'course_id': str(course_id), + 'error': error, + 'enrollment_status': enrollment_status + } - return JsonResponse(response_payload) + return JsonResponse(response_payload) class StudentProgressUrlSerializer(serializers.Serializer): diff --git a/lms/djangoapps/instructor/views/api_urls.py b/lms/djangoapps/instructor/views/api_urls.py index a248b46ae531..92d5f46bc70e 100644 --- a/lms/djangoapps/instructor/views/api_urls.py +++ b/lms/djangoapps/instructor/views/api_urls.py @@ -32,7 +32,8 @@ path('get_issued_certificates/', api.get_issued_certificates, name='get_issued_certificates'), path('get_students_who_may_enroll', api.GetStudentsWhoMayEnroll.as_view(), name='get_students_who_may_enroll'), path('get_anon_ids', api.GetAnonIds.as_view(), name='get_anon_ids'), - path('get_student_enrollment_status', api.get_student_enrollment_status, name="get_student_enrollment_status"), + path('get_student_enrollment_status', api.GetStudentEnrollmentStatus.as_view(), + name="get_student_enrollment_status"), path('get_student_progress_url', api.StudentProgressUrl.as_view(), name='get_student_progress_url'), path('reset_student_attempts', api.ResetStudentAttempts.as_view(), name='reset_student_attempts'), path('rescore_problem', api.rescore_problem, name='rescore_problem'), diff --git a/lms/djangoapps/instructor/views/serializer.py b/lms/djangoapps/instructor/views/serializer.py index 5d123ad66c81..59ac66ab838b 100644 --- a/lms/djangoapps/instructor/views/serializer.py +++ b/lms/djangoapps/instructor/views/serializer.py @@ -31,23 +31,14 @@ class Meta: fields = ['username', 'email', 'first_name', 'last_name'] -class AccessSerializer(serializers.Serializer): +class UniqueStudentIdentifierSerializer(serializers.Serializer): """ - Serializer for managing user access changes. - This serializer validates and processes the data required to modify - user access within a system. + Serializer for identifying unique_student. """ unique_student_identifier = serializers.CharField( max_length=255, help_text="Email or username of user to change access" ) - rolename = serializers.CharField( - help_text="Role name to assign to the user" - ) - action = serializers.ChoiceField( - choices=['allow', 'revoke'], - help_text="Action to perform on the user's access" - ) def validate_unique_student_identifier(self, value): """ @@ -61,6 +52,21 @@ def validate_unique_student_identifier(self, value): return user +class AccessSerializer(UniqueStudentIdentifierSerializer): + """ + Serializer for managing user access changes. + This serializer validates and processes the data required to modify + user access within a system. + """ + rolename = serializers.CharField( + help_text="Role name to assign to the user" + ) + action = serializers.ChoiceField( + choices=['allow', 'revoke'], + help_text="Action to perform on the user's access" + ) + + class ListInstructorTaskInputSerializer(serializers.Serializer): # pylint: disable=abstract-method """ Serializer for handling the input data for the problem response report generation API.