def test_get_social_auth(self): """ Tests that get_social_auth returns a user's edX social auth object, and if multiple edX social auth objects exists, it raises an exception """ assert get_social_auth(self.user) == self.user.social_auth.get(provider=EdxOrgOAuth2.name) UserSocialAuthFactory.create(user=self.user, uid='other name') with self.assertRaises(MultipleObjectsReturned): get_social_auth(self.user)
def post(self, request): """ Audit enrolls the user in a course in edx """ course_id = request.data.get('course_id') if course_id is None: raise ValidationError('course id missing in the request') # get the credentials for the current user for edX user_social = get_social_auth(request.user) try: utils.refresh_user_token(user_social) except utils.InvalidCredentialStored as exc: log.error( "Error while refreshing credentials for user %s", get_social_username(request.user), ) return Response( status=exc.http_status_code, data={'error': str(exc)} ) # create an instance of the client to query edX edx_client = EdxApi(user_social.extra_data, settings.EDXORG_BASE_URL) try: enrollment = edx_client.enrollments.create_audit_student_enrollment(course_id) except HTTPError as exc: if exc.response.status_code == status.HTTP_400_BAD_REQUEST: raise PossiblyImproperlyConfigured( 'Got a 400 status code from edX server while trying to create ' 'audit enrollment. This might happen if the course is improperly ' 'configured on MicroMasters. Course key ' '{course_key}, edX user "{edX_user}"'.format( edX_user=get_social_username(request.user), course_key=course_id, ) ) log.error( "Http error from edX while creating audit enrollment for course key %s for edX user %s", course_id, get_social_username(request.user), ) return Response( status=status.HTTP_500_INTERNAL_SERVER_ERROR, data={'error': str(exc)} ) except Exception as exc: # pylint: disable=broad-except log.exception( "Error creating audit enrollment for course key %s for edX user %s", course_id, get_social_username(request.user), ) return Response( status=status.HTTP_500_INTERNAL_SERVER_ERROR, data={'error': str(exc)} ) CachedEdxDataApi.update_cached_enrollment(request.user, enrollment, enrollment.course_id, index_user=True) return Response( data=enrollment.json )
def get(self, request, username, *args, **kargs): # pylint: disable=unused-argument """ Returns information needed to display the user dashboard for all the programs the user is enrolled in. """ user = get_object_or_404(User, social_auth__uid=username, social_auth__provider=EdxOrgOAuth2.name) # get the credentials for the current user for edX edx_client = None if user == request.user: user_social = get_social_auth(request.user) try: utils.refresh_user_token(user_social) except utils.InvalidCredentialStored as exc: return Response(status=exc.http_status_code, data={'error': str(exc)}) except: # pylint: disable=bare-except log.exception( 'Impossible to refresh user credentials in dashboard view') # create an instance of the client to query edX edx_client = EdxApi(user_social.extra_data, settings.EDXORG_BASE_URL) try: program_dashboard = get_user_program_info(user, edx_client) except utils.InvalidCredentialStored as exc: log.exception( 'Access token for user %s is fresh but invalid; forcing login.', user.username) return Response(status=exc.http_status_code, data={'error': str(exc)}) return Response(status=status.HTTP_200_OK, data=program_dashboard)
def refresh_user_data(user_id): """ Refresh the edx cache data for a user. Note that this function will not raise an exception on error, instead the errors are logged. Args: user_id (int): The user id """ # pylint: disable=bare-except try: user = User.objects.get(pk=user_id) except: log.exception('edX data refresh task: unable to get user "%s"', user_id) return # get the credentials for the current user for edX try: user_social = get_social_auth(user) except: log.exception('user "%s" does not have edX credentials', user.username) return try: utils.refresh_user_token(user_social) except: save_cache_update_failure(user_id) log.exception("Unable to refresh token for student %s", user.username) return try: edx_client = EdxApi(user_social.extra_data, settings.EDXORG_BASE_URL) except: log.exception("Unable to create an edX client object for student %s", user.username) return for cache_type in CachedEdxDataApi.SUPPORTED_CACHES: try: CachedEdxDataApi.update_cache_if_expired(user, edx_client, cache_type) except: save_cache_update_failure(user_id) log.exception("Unable to refresh cache %s for student %s", cache_type, user.username) continue
def update_all_cached_grade_data(cls, user): """ Updates only certificates and Current grade. Used before a final grade freeze. Args: user (django.contrib.auth.models.User): A user Returns: None """ # get the credentials for the current user for edX user_social = get_social_auth(user) utils.refresh_user_token(user_social) # create an instance of the client to query edX edx_client = EdxApi(user_social.extra_data, settings.EDXORG_BASE_URL) cls.update_cached_certificates(user, edx_client) cls.update_cached_current_grades(user, edx_client)
def enroll_user_on_success(order): """ Enroll user after they made a successful purchase. Args: order (Order): An order to be fulfilled Returns: None """ user_social = get_social_auth(order.user) enrollments_client = EdxApi(user_social.extra_data, settings.EDXORG_BASE_URL).enrollments existing_enrollments = enrollments_client.get_student_enrollments() exceptions = [] enrollments = [] for line in order.line_set.all(): course_key = line.course_key try: if not existing_enrollments.is_enrolled_in(course_key): enrollments.append( enrollments_client.create_audit_student_enrollment( course_key)) except Exception as ex: # pylint: disable=broad-except log.exception( "Error creating audit enrollment for course key %s for user %s", course_key, get_social_username(order.user), ) exceptions.append(ex) for enrollment in enrollments: CachedEdxDataApi.update_cached_enrollment( order.user, enrollment, enrollment.course_id, index_user=True, ) if exceptions: raise EcommerceEdxApiException(exceptions)
def enroll_user_on_success(order): """ Enroll user after they made a successful purchase. Args: order (Order): An order to be fulfilled Returns: None """ user_social = get_social_auth(order.user) enrollments_client = EdxApi(user_social.extra_data, settings.EDXORG_BASE_URL).enrollments existing_enrollments = enrollments_client.get_student_enrollments() exceptions = [] enrollments = [] for line in order.line_set.all(): course_key = line.course_key try: if not existing_enrollments.is_enrolled_in(course_key): enrollments.append(enrollments_client.create_audit_student_enrollment(course_key)) except Exception as ex: # pylint: disable=broad-except log.exception( "Error creating audit enrollment for course key %s for user %s", course_key, get_social_username(order.user), ) exceptions.append(ex) for enrollment in enrollments: CachedEdxDataApi.update_cached_enrollment( order.user, enrollment, enrollment.course_id, index_user=True, ) if exceptions: raise EcommerceEdxApiException(exceptions)
def get(self, request, username, *args, **kargs): # pylint: disable=unused-argument """ Returns information needed to display the user dashboard for all the programs the user is enrolled in. """ user = get_object_or_404( User, social_auth__uid=username, social_auth__provider=EdxOrgOAuth2.name ) # get the credentials for the current user for edX edx_client = None if user == request.user: user_social = get_social_auth(request.user) try: utils.refresh_user_token(user_social) except utils.InvalidCredentialStored as exc: return Response( status=exc.http_status_code, data={'error': str(exc)} ) except: # pylint: disable=bare-except log.exception('Impossible to refresh user credentials in dashboard view') # create an instance of the client to query edX edx_client = EdxApi(user_social.extra_data, settings.EDXORG_BASE_URL) try: program_dashboard = get_user_program_info(user, edx_client) except utils.InvalidCredentialStored as exc: log.exception('Access token for user %s is fresh but invalid; forcing login.', user.username) return Response( status=exc.http_status_code, data={'error': str(exc)} ) return Response( status=status.HTTP_200_OK, data=program_dashboard )
def get_social_auth_uid(self, user): """Helper method to get social_auth uid for a user""" return get_social_auth(user).uid