def get(self, request, *args, **kargs): # pylint: disable=unused-argument, no-self-use """ Returns information needed to display the user dashboard for a program. """ # get the credentials for the current user for edX user_social = request.user.social_auth.get(provider=EdxOrgOAuth2.name) try: utils.refresh_user_token(user_social) except utils.InvalidCredentialStored as exc: 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) # get an enrollments client for the student enrollments = get_student_enrollments(request.user, edx_client) # get a certificates client for the student certificates = get_student_certificates(request.user, edx_client) response_data = [] for program in Program.objects.filter(live=True): response_data.append(get_info_for_program(program, enrollments, certificates)) return Response(response_data)
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 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 test_no_refresh(self, mock_refresh): """The refresh does not need to be called""" extra_data = { "updated_at": (self.now - timedelta(minutes=1)).timestamp(), "expires_in": 31535999 # 1 year - 1 second } social_user = self.update_social_extra_data(extra_data) utils.refresh_user_token(social_user) assert not mock_refresh.called
def test_refresh(self, mock_refresh): """The refresh needs to be called""" extra_data = { "updated_at": (self.now - timedelta(weeks=1)).timestamp(), "expires_in": 100 # seconds } social_user = self.update_social_extra_data(extra_data) utils.refresh_user_token(social_user) assert mock_refresh.called
def test_refresh_no_extradata(self, mock_refresh): """The refresh needs to be called because there is not valid timestamps""" social_user = self.user.social_auth.get(provider=EdxOrgOAuth2.name) social_user.extra_data = { "access_token": "fooooootoken", "refresh_token": "baaaarrefresh" } social_user.save() utils.refresh_user_token(social_user) assert mock_refresh.called
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 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 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 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 )