Commit 52ab2b13 by Calen Pennington

Make FieldDataCache use the user from scope_ids, rather than its pre-configured user

Co-author: Ned Batchelder <ned@edx.org>
parent 1205173d
...@@ -14,10 +14,11 @@ from .models import ( ...@@ -14,10 +14,11 @@ from .models import (
import logging import logging
from django.db import DatabaseError from django.db import DatabaseError
from django.contrib.auth.models import User
from xblock.runtime import KeyValueStore from xblock.runtime import KeyValueStore
from xblock.exceptions import KeyValueMultiSaveError, InvalidScopeError from xblock.exceptions import KeyValueMultiSaveError, InvalidScopeError
from xblock.fields import Scope from xblock.fields import Scope, UserScope
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -226,10 +227,15 @@ class FieldDataCache(object): ...@@ -226,10 +227,15 @@ class FieldDataCache(object):
if field_object is not None: if field_object is not None:
return field_object return field_object
if key.scope.user == UserScope.ONE and not self.user.is_anonymous():
# If we're getting user data, we expect that the key matches the
# user we were constructed for.
assert key.user_id == self.user.id
if key.scope == Scope.user_state: if key.scope == Scope.user_state:
field_object, _ = StudentModule.objects.get_or_create( field_object, _ = StudentModule.objects.get_or_create(
course_id=self.course_id, course_id=self.course_id,
student=self.user, student=User.objects.get(id=key.user_id),
module_state_key=key.block_scope_id.url(), module_state_key=key.block_scope_id.url(),
defaults={ defaults={
'state': json.dumps({}), 'state': json.dumps({}),
...@@ -245,12 +251,12 @@ class FieldDataCache(object): ...@@ -245,12 +251,12 @@ class FieldDataCache(object):
field_object, _ = XModuleStudentPrefsField.objects.get_or_create( field_object, _ = XModuleStudentPrefsField.objects.get_or_create(
field_name=key.field_name, field_name=key.field_name,
module_type=key.block_scope_id, module_type=key.block_scope_id,
student=self.user, student=User.objects.get(id=key.user_id),
) )
elif key.scope == Scope.user_info: elif key.scope == Scope.user_info:
field_object, _ = XModuleStudentInfoField.objects.get_or_create( field_object, _ = XModuleStudentInfoField.objects.get_or_create(
field_name=key.field_name, field_name=key.field_name,
student=self.user, student=User.objects.get(id=key.user_id),
) )
cache_key = self._cache_key_from_kvs_key(key) cache_key = self._cache_key_from_kvs_key(key)
...@@ -347,7 +353,7 @@ class DjangoKeyValueStore(KeyValueStore): ...@@ -347,7 +353,7 @@ class DjangoKeyValueStore(KeyValueStore):
# the list of successful saves # the list of successful saves
saved_fields.extend([field.field_name for field in field_objects[field_object]]) saved_fields.extend([field.field_name for field in field_objects[field_object]])
except DatabaseError: except DatabaseError:
log.error('Error saving fields %r', field_objects[field_object]) log.exception('Error saving fields %r', field_objects[field_object])
raise KeyValueMultiSaveError(saved_fields) raise KeyValueMultiSaveError(saved_fields)
def delete(self, key): def delete(self, key):
......
...@@ -40,11 +40,14 @@ def mock_descriptor(fields=[]): ...@@ -40,11 +40,14 @@ def mock_descriptor(fields=[]):
location = partial(Location, 'i4x', 'edX', 'test_course', 'problem') location = partial(Location, 'i4x', 'edX', 'test_course', 'problem')
course_id = 'edX/test_course/test' course_id = 'edX/test_course/test'
# The user ids here are 1 because we make a student in the setUp functions, and
# they get an id of 1. There's an assertion in setUp to ensure that assumption
# is still true.
user_state_summary_key = partial(DjangoKeyValueStore.Key, Scope.user_state_summary, None, location('def_id')) user_state_summary_key = partial(DjangoKeyValueStore.Key, Scope.user_state_summary, None, location('def_id'))
settings_key = partial(DjangoKeyValueStore.Key, Scope.settings, None, location('def_id')) settings_key = partial(DjangoKeyValueStore.Key, Scope.settings, None, location('def_id'))
user_state_key = partial(DjangoKeyValueStore.Key, Scope.user_state, 'user', location('def_id')) user_state_key = partial(DjangoKeyValueStore.Key, Scope.user_state, 1, location('def_id'))
prefs_key = partial(DjangoKeyValueStore.Key, Scope.preferences, 'user', 'MockProblemModule') prefs_key = partial(DjangoKeyValueStore.Key, Scope.preferences, 1, 'MockProblemModule')
user_info_key = partial(DjangoKeyValueStore.Key, Scope.user_info, 'user', None) user_info_key = partial(DjangoKeyValueStore.Key, Scope.user_info, 1, None)
class StudentModuleFactory(cmfStudentModuleFactory): class StudentModuleFactory(cmfStudentModuleFactory):
...@@ -76,6 +79,7 @@ class TestStudentModuleStorage(TestCase): ...@@ -76,6 +79,7 @@ class TestStudentModuleStorage(TestCase):
def setUp(self): def setUp(self):
student_module = StudentModuleFactory(state=json.dumps({'a_field': 'a_value', 'b_field': 'b_value'})) student_module = StudentModuleFactory(state=json.dumps({'a_field': 'a_value', 'b_field': 'b_value'}))
self.user = student_module.student self.user = student_module.student
self.assertEqual(self.user.id, 1) # check our assumption hard-coded in the key functions above.
self.field_data_cache = FieldDataCache([mock_descriptor([mock_field(Scope.user_state, 'a_field')])], course_id, self.user) self.field_data_cache = FieldDataCache([mock_descriptor([mock_field(Scope.user_state, 'a_field')])], course_id, self.user)
self.kvs = DjangoKeyValueStore(self.field_data_cache) self.kvs = DjangoKeyValueStore(self.field_data_cache)
...@@ -152,6 +156,7 @@ class TestStudentModuleStorage(TestCase): ...@@ -152,6 +156,7 @@ class TestStudentModuleStorage(TestCase):
class TestMissingStudentModule(TestCase): class TestMissingStudentModule(TestCase):
def setUp(self): def setUp(self):
self.user = UserFactory.create(username='user') self.user = UserFactory.create(username='user')
self.assertEqual(self.user.id, 1) # check our assumption hard-coded in the key functions above.
self.field_data_cache = FieldDataCache([mock_descriptor()], course_id, self.user) self.field_data_cache = FieldDataCache([mock_descriptor()], course_id, self.user)
self.kvs = DjangoKeyValueStore(self.field_data_cache) self.kvs = DjangoKeyValueStore(self.field_data_cache)
......
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