Commit 521521c6 by David Ormsbee

Merge pull request #559 from MITx/kimth/send-idhash

Kimth/send idhash
parents bf6fe102 fa074277
...@@ -1010,7 +1010,7 @@ class CodeResponse(LoncapaResponse): ...@@ -1010,7 +1010,7 @@ class CodeResponse(LoncapaResponse):
''' '''
Grade student code using an external queueing server, called 'xqueue' Grade student code using an external queueing server, called 'xqueue'
Expects 'xqueue' dict in ModuleSystem with the following keys: Expects 'xqueue' dict in ModuleSystem with the following keys that are needed by CodeResponse:
system.xqueue = { 'interface': XqueueInterface object, system.xqueue = { 'interface': XqueueInterface object,
'callback_url': Per-StudentModule callback URL where results are posted (string), 'callback_url': Per-StudentModule callback URL where results are posted (string),
'default_queuename': Default queuename to submit request (string) 'default_queuename': Default queuename to submit request (string)
...@@ -1126,22 +1126,34 @@ class CodeResponse(LoncapaResponse): ...@@ -1126,22 +1126,34 @@ class CodeResponse(LoncapaResponse):
# Prepare xqueue request # Prepare xqueue request
#------------------------------------------------------------ #------------------------------------------------------------
qinterface = self.system.xqueue['interface'] qinterface = self.system.xqueue['interface']
qtime = datetime.strftime(datetime.now(), xqueue_interface.dateformat)
anonymous_student_id = self.system.anonymous_student_id
# Generate header # Generate header
queuekey = xqueue_interface.make_hashkey(str(self.system.seed)+self.answer_id) queuekey = xqueue_interface.make_hashkey(str(self.system.seed) + qtime +
anonymous_student_id +
self.answer_id)
xheader = xqueue_interface.make_xheader(lms_callback_url=self.system.xqueue['callback_url'], xheader = xqueue_interface.make_xheader(lms_callback_url=self.system.xqueue['callback_url'],
lms_key=queuekey, lms_key=queuekey,
queue_name=self.queue_name) queue_name=self.queue_name)
# Generate body # Generate body
if is_list_of_files(submission): if is_list_of_files(submission):
self.context.update({'submission': queuekey}) # For tracking. TODO: May want to record something else here self.context.update({'submission': ''}) # TODO: Get S3 pointer from the Queue
else: else:
self.context.update({'submission': submission}) self.context.update({'submission': submission})
contents = self.payload.copy() contents = self.payload.copy()
# Metadata related to the student submission revealed to the external grader
student_info = {'anonymous_student_id': anonymous_student_id,
'submission_time': qtime,
}
contents.update({'student_info': json.dumps(student_info)})
# Submit request. When successful, 'msg' is the prior length of the queue # Submit request. When successful, 'msg' is the prior length of the queue
if is_list_of_files(submission): if is_list_of_files(submission):
contents.update({'student_response': ''}) # TODO: Is there any information we want to send here? contents.update({'student_response': ''}) # TODO: Is there any information we want to send here?
...@@ -1154,7 +1166,6 @@ class CodeResponse(LoncapaResponse): ...@@ -1154,7 +1166,6 @@ class CodeResponse(LoncapaResponse):
body=json.dumps(contents)) body=json.dumps(contents))
# State associated with the queueing request # State associated with the queueing request
qtime = datetime.strftime(datetime.now(), xqueue_interface.dateformat)
queuestate = {'key': queuekey, queuestate = {'key': queuekey,
'time': qtime, 'time': qtime,
} }
......
...@@ -5,20 +5,17 @@ import hashlib ...@@ -5,20 +5,17 @@ import hashlib
import json import json
import logging import logging
import requests import requests
import time
log = logging.getLogger('mitx.' + __name__) log = logging.getLogger('mitx.' + __name__)
dateformat = '%Y%m%d%H%M%S' dateformat = '%Y%m%d%H%M%S'
def make_hashkey(seed=None): def make_hashkey(seed):
''' '''
Generate a string key by hashing Generate a string key by hashing
''' '''
h = hashlib.md5() h = hashlib.md5()
if seed is not None: h.update(str(seed))
h.update(str(seed))
h.update(str(time.time()))
return h.hexdigest() return h.hexdigest()
......
...@@ -38,7 +38,8 @@ i4xs = ModuleSystem( ...@@ -38,7 +38,8 @@ i4xs = ModuleSystem(
filestore=fs.osfs.OSFS(os.path.dirname(os.path.realpath(__file__))+"/test_files"), filestore=fs.osfs.OSFS(os.path.dirname(os.path.realpath(__file__))+"/test_files"),
debug=True, debug=True,
xqueue={'interface':None, 'callback_url':'/', 'default_queuename': 'testqueue', 'waittime': 10}, xqueue={'interface':None, 'callback_url':'/', 'default_queuename': 'testqueue', 'waittime': 10},
node_path=os.environ.get("NODE_PATH", "/usr/local/lib/node_modules") node_path=os.environ.get("NODE_PATH", "/usr/local/lib/node_modules"),
anonymous_student_id = 'student'
) )
......
...@@ -717,7 +717,8 @@ class ModuleSystem(object): ...@@ -717,7 +717,8 @@ class ModuleSystem(object):
filestore=None, filestore=None,
debug=False, debug=False,
xqueue=None, xqueue=None,
node_path=""): node_path="",
anonymous_student_id=''):
''' '''
Create a closure around the system environment. Create a closure around the system environment.
...@@ -742,11 +743,16 @@ class ModuleSystem(object): ...@@ -742,11 +743,16 @@ class ModuleSystem(object):
at settings.DATA_DIR. at settings.DATA_DIR.
xqueue - Dict containing XqueueInterface object, as well as parameters xqueue - Dict containing XqueueInterface object, as well as parameters
for the specific StudentModule for the specific StudentModule:
xqueue = {'interface': XQueueInterface object,
'callback_url': Callback into the LMS,
'queue_name': Target queuename in Xqueue}
replace_urls - TEMPORARY - A function like static_replace.replace_urls replace_urls - TEMPORARY - A function like static_replace.replace_urls
that capa_module can use to fix up the static urls in that capa_module can use to fix up the static urls in
ajax results. ajax results.
anonymous_student_id - Used for tracking modules with student id
''' '''
self.ajax_url = ajax_url self.ajax_url = ajax_url
self.xqueue = xqueue self.xqueue = xqueue
...@@ -758,6 +764,7 @@ class ModuleSystem(object): ...@@ -758,6 +764,7 @@ class ModuleSystem(object):
self.seed = user.id if user is not None else 0 self.seed = user.id if user is not None else 0
self.replace_urls = replace_urls self.replace_urls = replace_urls
self.node_path = node_path self.node_path = node_path
self.anonymous_student_id = anonymous_student_id
def get(self, attr): def get(self, attr):
''' provide uniform access to attributes (like etree).''' ''' provide uniform access to attributes (like etree).'''
......
import hashlib
import json import json
import logging import logging
import sys import sys
...@@ -174,6 +175,12 @@ def _get_module(user, request, location, student_module_cache, course_id, positi ...@@ -174,6 +175,12 @@ def _get_module(user, request, location, student_module_cache, course_id, positi
if not has_access(user, descriptor, 'load'): if not has_access(user, descriptor, 'load'):
return None return None
# Anonymized student identifier
h = hashlib.md5()
h.update(settings.SECRET_KEY)
h.update(str(user.id))
anonymous_student_id = h.hexdigest()
# Only check the cache if this module can possibly have state # Only check the cache if this module can possibly have state
instance_module = None instance_module = None
shared_module = None shared_module = None
...@@ -246,7 +253,8 @@ def _get_module(user, request, location, student_module_cache, course_id, positi ...@@ -246,7 +253,8 @@ def _get_module(user, request, location, student_module_cache, course_id, positi
# a module is coming through get_html and is therefore covered # a module is coming through get_html and is therefore covered
# by the replace_static_urls code below # by the replace_static_urls code below
replace_urls=replace_urls, replace_urls=replace_urls,
node_path=settings.NODE_PATH node_path=settings.NODE_PATH,
anonymous_student_id=anonymous_student_id
) )
# pass position specified in URL to module through ModuleSystem # pass position specified in URL to module through ModuleSystem
system.set('position', position) system.set('position', position)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment