def test_post_outcome_request(self): request_headers = {"User-Agent": "unit-test"} request = OutcomeRequest(headers=request_headers) self.assertRaises(InvalidLTIConfigError, request.post_outcome_request) request.consumer_key = 'consumer' request.consumer_secret = 'secret' request.lis_outcome_service_url = 'http://example.edu/' request.lis_result_sourcedid = 'foo' request.operation = REPLACE_REQUEST with HTTMock(response_content): resp = request.post_outcome_request(nonce='my_nonce', timestamp='1234567890') self.assertIsInstance(resp, OutcomeResponse) request = resp.post_response.request self.assertTrue('authorization' in request.headers) self.assertEqual(request.headers.get('user-agent'), b"unit-test") self.assertEqual(request.headers.get('content-type'), b"application/xml") auth_header = unquote(request.headers['authorization'].decode('utf-8')) correct = ('OAuth ' 'oauth_nonce="my_nonce", oauth_timestamp="1234567890", ' 'oauth_version="1.0", oauth_signature_method="HMAC-SHA1", ' 'oauth_consumer_key="consumer", ' 'oauth_body_hash="glWvnsZZ8lMif1ATz8Tx64CTTaY=", ' 'oauth_signature="XR6A1CmUauXZdJZXa1pJpTQi6OQ="') self.assertEqual(auth_header, correct)
def test_has_required_attributes(self): request = OutcomeRequest() self.assertFalse(request.has_required_attributes()) request.consumer_key = 'foo' request.consumer_secret = 'bar' self.assertFalse(request.has_required_attributes()) request.lis_outcome_service_url = 'http://example.edu/' request.lis_result_sourcedid = 1 request.operation = 'baz' self.assertTrue(request.has_required_attributes())
def send_grade_update(consumer_key, consumer_secret, lis_outcome_service_url, lis_result_sourcedid, score): """ Send lms grade for an lti component :param consumer_key: lti client key :param consumer_secret: lti client secret :param lis_outcome_service_url: outcome service url to send outcome request to :param lis_result_sourcedid: context identifier for consumer to use :param score: score between 0.0 and 1.0 :return: """ outcome_request = OutcomeRequest() outcome_request.consumer_key = consumer_key outcome_request.consumer_secret = consumer_secret outcome_request.lis_outcome_service_url = lis_outcome_service_url outcome_request.lis_result_sourcedid = lis_result_sourcedid # construct info string for logging args = "score={}, lis_outcome_service_url={} lis_result_sourcedid={}, consumer_key={}, consumer_secret={}, ".format( score, lis_outcome_service_url, lis_result_sourcedid, consumer_key, consumer_secret) log.debug("Updating LMS grade, with parameters: {}".format(args)) # send request to update score outcome_request.post_replace_result(score) # check out the request response lms_response = outcome_request.outcome_response # logging if lms_response.is_success(): log.info("Successfully sent updated grade to LMS. {}".format(args)) elif lms_response.is_processing(): log.info( "Grade update is being processed by LMS. {}, comment: {}".format( args, 'processing')) elif lms_response.has_warning(): log.warning( "Grade update response has warnings. {}, comment={}".format( args, 'processing')) else: log.error("Grade update request failed. {}, comment={}".format( args, lms_response.code_major)) return lms_response
def update_lms_grades(request=None, sequence=None): """Send grade update to LMS (LTI Tool).""" outcome_request = OutcomeRequest().from_post_request( request) if request else OutcomeRequest() outcome_service = sequence.outcome_service if outcome_service is None: log.info( f"Sequence: {sequence} doesn't contain an outcome service, grade is not sent." ) return consumer = outcome_service.lms_lti_connection outcome_request.consumer_key = consumer.consumer_key outcome_request.consumer_secret = consumer.consumer_secret outcome_request.lis_outcome_service_url = outcome_service.lis_outcome_service_url outcome_request.lis_result_sourcedid = sequence.lis_result_sourcedid log.debug( "Update LMS grades. Used sequence = {} is completed = {}, grading_policy = {}" .format(sequence, sequence.completed, sequence.collection_order.grading_policy)) score = sequence.collection_order.grading_policy.calculate_grade(sequence) outcome_request.post_replace_result(score) lms_response = outcome_request.outcome_response user_id = sequence.lti_user if lms_response.is_success(): log.info( "Successfully sent updated grade to LMS. Student:{}, grade:{}, comment: success" .format(user_id, score)) elif lms_response.is_processing(): log.info( "Grade update is being processed by LMS. Student:{}, grade:{}, comment: processing" .format(user_id, score)) elif lms_response.has_warning(): log.warning( "Grade update response has warnings. Student:{}, grade:{}, comment: warning" .format(user_id, score)) else: log.error( "Grade update request failed. Student:{}, grade:{}, comment:{}". format(user_id, score, lms_response.code_major))
def test_post_outcome_request(self): request = OutcomeRequest() self.assertRaises(InvalidLTIConfigError, request.post_outcome_request) request.consumer_key = 'consumer' request.consumer_secret = 'secret' request.lis_outcome_service_url = 'http://example.edu/' request.lis_result_sourcedid = 'foo' request.operation = REPLACE_REQUEST with HTTMock(response_content): resp = request.post_outcome_request( nonce='my_nonce', timestamp='1234567890' ) self.assertIsInstance(resp, OutcomeResponse) request = resp.post_response.request self.assertTrue('authorization' in request.headers) auth_header = unquote(request.headers['authorization'].decode('utf-8')) correct = ('OAuth ' 'oauth_nonce="my_nonce", oauth_timestamp="1234567890", ' 'oauth_version="1.0", oauth_signature_method="HMAC-SHA1", ' 'oauth_consumer_key="consumer", ' 'oauth_body_hash="glWvnsZZ8lMif1ATz8Tx64CTTaY=", ' 'oauth_signature="XR6A1CmUauXZdJZXa1pJpTQi6OQ="') self.assertEqual(auth_header, correct)