def track_user_event(user, event_name, data, page): """ Marks a user's progress in the user's CompletionProfile whenever an appropriate event is logged, and sends the report to the third-party API. Args: user (User): the user object. event_name (str): the name of the logged event. Event names are specific to edX events and are mapped to the events tracked for the completion report. data (str or dict): in the event of a watched video, edX logs data in a dict where the `id` key contains the video block ID. For problems this argument contains the usage key. page (str): URL where the event was triggered. Used to extract the course ID. """ if event_name in EVENT_BLOCK_MAP: block_type = EVENT_BLOCK_MAP[event_name] course_id = extract_course_id_from_url(page) course_key = CourseKey.from_string(course_id) if block_type == 'problem': data_id = extract_problem_id(data) elif block_type == 'video': data_id = data['id'] usage_key = BlockUsageLocator(course_key, block_type, data_id) CompletionProfile.mark_progress(user, course_key, usage_key.block_id)
def test_create_existing_completion_profile_from_data(self): """Exception is raised when trying to create existing Completion Profile.""" self.create_completion_profile(reg_key=self.registration_key) self.assert_object_count(completion_profile_count=1, user_count=1) with self.assertRaises(CompletionProfileAlreadyExists): CompletionProfile.create_from_data(self.registration_data) self.assert_object_count(completion_profile_count=1, user_count=1)
def test_create_new_completion_profile_from_data(self, mocked_fn): self.assert_object_count(completion_profile_count=0, user_count=1) completion_profile = CompletionProfile.create_from_data(self.registration_data) self.assert_completion_profile(completion_profile, self.user) self.assert_object_count(completion_profile_count=1, user_count=1) self.assertFalse(mocked_fn.called)
def test_create_existing_user(self, mocked_fn): """Creates new completion profile with existing user.""" mocked_fn.return_value = self.registration_data self.assert_object_count(completion_profile_count=0, user_count=1) completion_profile = CompletionProfile.create_from_key(self.registration_key) self.assert_completion_profile(completion_profile, self.user) self.assert_object_count(completion_profile_count=1, user_count=1) self.assertTrue(mocked_fn.called)
def new_registration_action_handler(self, registration_data): """ Handles the NewRegistration action requests. Creates a new CompletionProfile based on the data fetched from ed2go API via the passed in registration_key value. Args: registration_data (dict): The fetched registration data. Returns: - response message - response status code - 201 if created, 400 if profile already exists """ registration_key = registration_data[c.REG_REGISTRATION_KEY] reference_id = registration_data[c.REG_REFERENCE_ID] try: completion_profile = CompletionProfile.create_from_data( registration_data) except CompletionProfileAlreadyExists: msg = 'Completion Profile already exists for registration key {reg_key}'.format( reg_key=registration_key) LOG.error(msg) self.update_registration_status_request( reg_key=registration_key, ref_id=reference_id, status=c.REG_REGISTRATION_REJECTED_STATUS, note='Registration already exists in the system') return msg, 400 except Exception as e: # pylint: disable=broad-except msg = self.handle_broad_exception(c.NEW_REGISTRATION_ACTION, registration_key, reference_id, e) return msg, 400 msg = 'Completion Profile created for user {user} and course {course}.'.format( user=completion_profile.user.username, course=completion_profile.course_key) LOG.info(msg) self.update_registration_status_request( reg_key=registration_key, ref_id=completion_profile.reference_id, status=c.REG_REGISTRATION_PROCESSED_STATUS) return msg, 201
def post(self, request): """ POST request handler. Handles the SSO requests from Ed2go. The request needs to be valid and have a registration key passed along. That registration key is then used to either retrieved already registered users, or create a new CompletionProfile object, or a new user altogether. At the end of this request there needs to be: * a user object corresponding with the registration data gathered from Ed2go registration service endpoint * a new CompletionProfile object if it didn't exist before * the user needs to be logged in * the user needs to be redirected to the course in corresponding CompletionProfile object. Invalid requests will be redirect to the passed in ReturnURL parameter, if there is one, else a 400 error will be returned. """ valid, msg = request_valid(request.POST, c.SSO_REQUEST) if not valid: return_url = request.POST.get(c.RETURN_URL) if return_url: LOG.info('Invalid SSO request. Redirecting to %s', return_url) return HttpResponseRedirect(return_url) return HttpResponse(msg, status=400) registration_key = request.POST[c.REGISTRATION_KEY] try: completion_profile = CompletionProfile.objects.get( registration_key=registration_key) except CompletionProfile.DoesNotExist: completion_profile = CompletionProfile.create_from_key( registration_key) user = completion_profile.user user.backend = settings.AUTHENTICATION_BACKENDS[0] login(request, user) return HttpResponseRedirect( reverse('course_root', kwargs={'course_id': completion_profile.course_key}))
def test_create_user_completion_profile(self, mocked_fn): """Creates new user and completion profile.""" mocked_fn.return_value = self.registration_data self.user.delete() self.assert_object_count(completion_profile_count=0, user_count=0) completion_profile = CompletionProfile.create_from_key(self.registration_key) user = completion_profile.user self.assert_completion_profile(completion_profile, user) self.assert_object_count(completion_profile_count=1, user_count=1) student_data = self.registration_data[c.REG_STUDENT] self.assertEqual(user.profile.name, student_data[c.REG_FIRST_NAME] + ' ' + student_data[c.REG_LAST_NAME]) self.assertEqual(user.profile.country, student_data[c.REG_COUNTRY]) self.assertEqual(user.profile.year_of_birth, self.year_of_birth) self.assertEqual(user.profile.get_meta()['ReturnURL'], self.registration_data[c.REG_RETURN_URL]) self.assertEqual( user.profile.get_meta()['StudentKey'], self.registration_data[c.REG_STUDENT][c.REG_STUDENT_KEY] ) self.assertTrue(mocked_fn.called)