def post(self, request): """ Unenrolls the specified user from all courses. """ try: # Get the username from the request. username = request.data['username'] # Ensure that a retirement request status row exists for this username. UserRetirementStatus.get_retirement_for_retirement_action(username) enrollments = api.get_enrollments(username) active_enrollments = [ enrollment for enrollment in enrollments if enrollment['is_active'] ] if len(active_enrollments) < 1: return Response(status=status.HTTP_204_NO_CONTENT) return Response(api.unenroll_user_from_all_courses(username)) except KeyError: return Response(u'Username not specified.', status=status.HTTP_404_NOT_FOUND) except UserRetirementStatus.DoesNotExist: return Response(u'No retirement request status for username.', status=status.HTTP_404_NOT_FOUND) except Exception as exc: # pylint: disable=broad-except return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def get(self, request, username_or_email): """ Returns a list of enrollments for the given user, along with information about previous manual enrollment changes. """ try: user = User.objects.get(Q(username=username_or_email) | Q(email=username_or_email)) except User.DoesNotExist: return JsonResponse([]) enrollments = get_enrollments(user.username, include_inactive=True) for enrollment in enrollments: # Folds the course_details field up into the main JSON object. enrollment.update(**enrollment.pop('course_details')) course_key = CourseKey.from_string(enrollment['course_id']) # Get the all courses modes and replace with existing modes. enrollment['course_modes'] = self.get_course_modes(course_key) # Add the price of the course's verified mode. self.include_verified_mode_info(enrollment, course_key) # Add manual enrollment history, if it exists enrollment['manual_enrollment'] = self.manual_enrollment_data(enrollment, course_key) if enterprise_enabled(): enterprise_enrollments_by_course_id = self._enterprise_course_enrollments_by_course_id(user) for enrollment in enrollments: enterprise_course_enrollments = enterprise_enrollments_by_course_id.get(enrollment['course_id'], []) enrollment['enterprise_course_enrollments'] = enterprise_course_enrollments return JsonResponse(enrollments)
def is_user_enrolled_in_program_type(user, program_type_slug, paid_modes_only=False, enrollments=None, entitlements=None): # lint-amnesty, pylint: disable=line-too-long """ This method will look at the learners Enrollments and Entitlements to determine if a learner is enrolled in a Program of the given type. NOTE: This method relies on the Program Cache right now. The goal is to move away from this in the future. Arguments: user (User): The user we are looking for. program_type_slug (str): The slug of the Program type we are looking for. paid_modes_only (bool): Request if the user is enrolled in a Program in a paid mode, False by default. enrollments (List[Dict]): Takes a serialized list of CourseEnrollments linked to the user entitlements (List[CourseEntitlement]): Take a list of CourseEntitlement objects linked to the user NOTE: Both enrollments and entitlements will be collected if they are not passed in. They are available as parameters in case they were already collected, to save duplicate queries in high traffic areas. Returns: bool: True is the user is enrolled in programs of the requested type """ course_runs = set() course_uuids = set() programs = get_programs_by_type(Site.objects.get_current(), program_type_slug) if not programs: return False for program in programs: for course in program.get('courses', []): course_uuids.add(course.get('uuid')) for course_run in course.get('course_runs', []): course_runs.add(course_run['key']) # Check Entitlements first, because there will be less Course Entitlements than # Course Run Enrollments. student_entitlements = entitlements if entitlements is not None else get_active_entitlement_list_for_user( user) for entitlement in student_entitlements: if str(entitlement.course_uuid) in course_uuids: return True student_enrollments = enrollments if enrollments is not None else get_enrollments( user.username) for enrollment in student_enrollments: course_run_id = enrollment['course_details']['course_id'] if paid_modes_only: course_run_key = CourseKey.from_string(course_run_id) paid_modes = [ mode.slug for mode in get_paid_modes_for_course(course_run_key) ] if enrollment[ 'mode'] in paid_modes and course_run_id in course_runs: return True elif course_run_id in course_runs: return True return False
def is_user_enrolled_in_program_type(user, program_type, paid_modes=False, enrollments=None, entitlements=None): """ This method will Look at the learners Enrollments and Entitlements to determine if a learner is enrolled in a Program of the given type. NOTE: This method relies on the Program Cache right now. The goal is to move away from this in the future. Arguments: user (User): The user we are looking for. program_type (String): The Program type we are looking for. paid_modes (bool): Request if the user is enrolled in a Program in a paid mode, False by default. Returns: bool: True is the user is enrolled in programs of the requested Type """ course_runs = set() course_uuids = set() programs = get_programs_by_type(Site.objects.get_current(), program_type) if not programs: return False for program in programs: for course in program.get('courses', []): course_uuids.add(course.get('uuid')) for course_run in course.get('course_runs', []): course_runs.add(course_run['key']) # Check Entitlements first, because there will be less Course Entitlements than # Course Run Enrollments. student_entitlements = entitlements if entitlements is not None else get_active_entitlement_list_for_user( user) for entitlement in student_entitlements: if str(entitlement.course_uuid) in course_uuids: return True student_enrollments = enrollments if enrollments is not None else get_enrollments( user.username) for enrollment in student_enrollments: course_run_id = enrollment['course_details']['course_id'] if paid_modes: course_run_key = CourseKey.from_string(course_run_id) paid_modes = [ mode.slug for mode in CourseMode.paid_modes_for_course(course_run_key) ] if enrollment[ 'mode'] in paid_modes and course_run_id in course_runs: return True elif course_run_id in course_runs: return True return False
def test_get_all_enrollments(self, enrollments): for enrollment in enrollments: fake_data_api.add_course(enrollment['course_id'], course_modes=enrollment['course_modes']) api.add_enrollment(self.USERNAME, enrollment['course_id'], enrollment['mode']) result = api.get_enrollments(self.USERNAME) self.assertEqual(len(enrollments), len(result)) for result_enrollment in result: self.assertIn( result_enrollment['course']['course_id'], [enrollment['course_id'] for enrollment in enrollments] )
def test_get_all_enrollments(self, enrollments): for enrollment in enrollments: fake_data_api.add_course(enrollment['course_id'], course_modes=enrollment['course_modes']) api.add_enrollment(self.USERNAME, enrollment['course_id'], enrollment['mode']) result = api.get_enrollments(self.USERNAME) assert len(enrollments) == len(result) for result_enrollment in result: assert result_enrollment['course']['course_id'] in [ enrollment['course_id'] for enrollment in enrollments ]
def post(self, request): """ Unenrolls the specified user from all courses. """ try: # Get the username from the request. username = request.data['username'] # Ensure that a retirement request status row exists for this username. UserRetirementStatus.get_retirement_for_retirement_action(username) enrollments = api.get_enrollments(username) active_enrollments = [enrollment for enrollment in enrollments if enrollment['is_active']] if len(active_enrollments) < 1: return Response(status=status.HTTP_204_NO_CONTENT) return Response(api.unenroll_user_from_all_courses(username)) except KeyError: return Response(u'Username not specified.', status=status.HTTP_404_NOT_FOUND) except UserRetirementStatus.DoesNotExist: return Response(u'No retirement request status for username.', status=status.HTTP_404_NOT_FOUND) except Exception as exc: # pylint: disable=broad-except return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def get(self, request, username_or_email): """ Returns a list of enrollments for the given user, along with information about previous manual enrollment changes. """ try: user = User.objects.get(Q(username=username_or_email) | Q(email=username_or_email)) except User.DoesNotExist: return JsonResponse([]) enrollments = get_enrollments(user.username, include_inactive=True) for enrollment in enrollments: # Folds the course_details field up into the main JSON object. enrollment.update(**enrollment.pop('course_details')) course_key = CourseKey.from_string(enrollment['course_id']) # get the all courses modes and replace with existing modes. enrollment['course_modes'] = self.get_course_modes(course_key) # Add the price of the course's verified mode. self.include_verified_mode_info(enrollment, course_key) # Add manual enrollment history, if it exists enrollment['manual_enrollment'] = self.manual_enrollment_data(enrollment, course_key) return JsonResponse(enrollments)
def get(self, request): """Gets a list of all course enrollments for a user. Returns a list for the currently logged in user, or for the user named by the 'user' GET parameter. If the username does not match that of the currently logged in user, only courses for which the currently logged in user has the Staff or Admin role are listed. As a result, a course team member can find out which of his or her own courses a particular learner is enrolled in. Only the Staff or Admin role (granted on the Django administrative console as the staff or instructor permission) in individual courses gives the requesting user access to enrollment data. Permissions granted at the organizational level do not give a user access to enrollment data for all of that organization's courses. Users who have the global staff permission can access all enrollment data for all courses. """ username = request.GET.get('user', request.user.username) try: enrollment_data = api.get_enrollments(username) except CourseEnrollmentError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ "message": (u"An error occurred while retrieving enrollments for user '{username}'" ).format(username=username) }) if username == request.user.username or GlobalStaff().has_user(request.user) or \ self.has_api_key_permissions(request): return Response(enrollment_data) filtered_data = [] for enrollment in enrollment_data: course_key = CourseKey.from_string( enrollment["course_details"]["course_id"]) if user_has_role(request.user, CourseStaffRole(course_key)): filtered_data.append(enrollment) return Response(filtered_data)
def get(self, request): """Gets a list of all course enrollments for a user. Returns a list for the currently logged in user, or for the user named by the 'user' GET parameter. If the username does not match that of the currently logged in user, only courses for which the currently logged in user has the Staff or Admin role are listed. As a result, a course team member can find out which of his or her own courses a particular learner is enrolled in. Only the Staff or Admin role (granted on the Django administrative console as the staff or instructor permission) in individual courses gives the requesting user access to enrollment data. Permissions granted at the organizational level do not give a user access to enrollment data for all of that organization's courses. Users who have the global staff permission can access all enrollment data for all courses. """ username = request.GET.get('user', request.user.username) try: enrollment_data = api.get_enrollments(username) except CourseEnrollmentError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ "message": ( u"An error occurred while retrieving enrollments for user '{username}'" ).format(username=username) } ) if username == request.user.username or GlobalStaff().has_user(request.user) or \ self.has_api_key_permissions(request): return Response(enrollment_data) filtered_data = [] for enrollment in enrollment_data: course_key = CourseKey.from_string(enrollment["course_details"]["course_id"]) if user_has_role(request.user, CourseStaffRole(course_key)): filtered_data.append(enrollment) return Response(filtered_data)
def get(self, request, username_or_email): """ * Example Request: - GET /support/onboarding_status/<username_or_email> * Example Response: { "verified_in": { "onboarding_status": "verified", "onboarding_link": "/courses/<course_id>/jump_to/<block_id>", "expiration_date": null, "onboarding_past_due": false, "onboarding_release_date": "2016-01-01T00:00:00+00:00", "review_requirements_url": "", "course_id": "<course_id>", "enrollment_date": "2021-12-29T14:30:18.895435Z", "instructor_dashboard_link": "/courses/<course_id>/instructor#view-special_exams" }, "current_status": { "onboarding_status": "other_course_approved", "onboarding_link": "/courses/<course_id>/jump_to/<block_id>", "expiration_date": "2023-12-29T15:52:28.245Z", "onboarding_past_due": false, "onboarding_release_date": "2020-01-01T00:00:00+00:00", "review_requirements_url": "", "course_id": "<course_id>", "enrollment_date": "2021-12-29T15:58:29.489916Z", "instructor_dashboard_link": "/courses/<course_id>/instructor#view-special_exams" } } """ # return dict onboarding_status = {'verified_in': None, 'current_status': None} # make object mutable request.GET = request.GET.copy() try: user = User.objects.get( Q(username=username_or_email) | Q(email=username_or_email)) except User.DoesNotExist: return JsonResponse(onboarding_status, status=404) request.GET['username'] = user.username enrollments = get_enrollments(user.username) enrollments = sorted(enrollments, key=lambda enrollment: enrollment['created'], reverse=True) enrollments = filter( lambda enrollment: enrollment['mode'] in [CourseMode.VERIFIED, CourseMode.PROFESSIONAL], enrollments) for enrollment in enrollments: request.GET['course_id'] = enrollment['course_details'][ 'course_id'] status = StudentOnboardingStatusView().get(request).data if 'onboarding_status' in status: status['course_id'] = enrollment['course_details']['course_id'] status['enrollment_date'] = enrollment['created'] status['instructor_dashboard_link'] = \ '/courses/{}/instructor#view-special_exams'.format(status['course_id']) # set most recent status only at first iteration if onboarding_status['current_status'] is None: onboarding_status['current_status'] = status # stay in loop to find original verified enrollment. Expensive! if status[ 'onboarding_status'] == ProctoredExamStudentAttemptStatus.verified: onboarding_status['verified_in'] = status break return JsonResponse(onboarding_status)