diff --git a/cms/djangoapps/contentstore/course_info_model.py b/cms/djangoapps/contentstore/course_info_model.py index 0e2551cac8..9dfd00a0da 100644 --- a/cms/djangoapps/contentstore/course_info_model.py +++ b/cms/djangoapps/contentstore/course_info_model.py @@ -56,7 +56,7 @@ def get_course_updates(location, provided_id): return course_upd_collection -def update_course_updates(location, update, passed_id=None): +def update_course_updates(location, update, passed_id=None, user=None): """ Either add or update the given course update. It will add it if the passed_id is absent or None. It will update it if it has an passed_id which has a valid value. Until updates have distinct values, the passed_id is the location url + an index @@ -102,7 +102,7 @@ def update_course_updates(location, update, passed_id=None): # update db record course_updates.data = html.tostring(course_html_parsed) - modulestore('direct').update_item(course_updates, 'course_info_model') + modulestore('direct').update_item(course_updates, user.id if user else None) return { "id": idx, @@ -125,7 +125,7 @@ def _course_info_content(html_parsed): # pylint: disable=unused-argument -def delete_course_update(location, update, passed_id): +def delete_course_update(location, update, passed_id, user): """ Delete the given course_info update from the db. Returns the resulting course_updates b/c their ids change. @@ -158,7 +158,7 @@ def delete_course_update(location, update, passed_id): # update db record course_updates.data = html.tostring(course_html_parsed) store = modulestore('direct') - store.update_item(course_updates, 'course_info_model') + store.update_item(course_updates, user.id) return get_course_updates(location, None) diff --git a/cms/djangoapps/contentstore/tests/test_checklists.py b/cms/djangoapps/contentstore/tests/test_checklists.py index 14164680fc..90dd40a8b7 100644 --- a/cms/djangoapps/contentstore/tests/test_checklists.py +++ b/cms/djangoapps/contentstore/tests/test_checklists.py @@ -54,7 +54,7 @@ class ChecklistTestCase(CourseTestCase): # Save the changed `checklists` to the underlying KeyValueStore before updating the modulestore self.course.save() modulestore = get_modulestore(self.course.location) - modulestore.update_item(self.course, self.user.pk) + modulestore.update_item(self.course, self.user.id) self.assertEqual(self.get_persisted_checklists(), None) response = self.client.get(self.checklists_url) self.assertEqual(payload, response.content) diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index c7f4b9339c..b904a65afc 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -124,7 +124,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): course.advanced_modules = component_types - store.update_item(course, self.user.username) + store.update_item(course, self.user.id) # just pick one vertical descriptor = store.get_items(Location('i4x', 'edX', 'simple', 'vertical', None, None))[0] @@ -263,7 +263,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): self.assertIn('graceperiod', own_metadata(html_module)) self.assertEqual(html_module.graceperiod, new_graceperiod) - draft_store.update_item(html_module, self.user.username) + draft_store.update_item(html_module, self.user.id) # read back to make sure it reads as 'own-metadata' html_module = draft_store.get_item(Location('i4x', 'edX', 'simple', 'html', 'test_html', None)) @@ -379,7 +379,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): self.assertEqual(course.tabs, expected_tabs) item.display_name = 'Updated' - module_store.update_item(item, self.user.username) + module_store.update_item(item, self.user.id) course = module_store.get_item(course_location) @@ -829,7 +829,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): self.assertIsInstance(html_module.data, basestring) new_data = html_module.data = html_module.data.replace('/static/', '/c4x/{0}/{1}/asset/'.format( source_location.org, source_location.course)) - module_store.update_item(html_module, None) + module_store.update_item(html_module, self.user.id) html_module = module_store.get_instance(source_location.course_id, html_module_location) self.assertEqual(new_data, html_module.data) @@ -862,7 +862,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): chapter.data = 'chapter data' with self.assertRaises(InvalidVersionError): - draft_store.update_item(chapter, 'user') + draft_store.update_item(chapter, self.user.id) self.assertRaises(InvalidVersionError, draft_store.unpublish, location) @@ -982,7 +982,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): 'sequential', 'vertical_sequential', None])) private_location_no_draft = private_vertical.location.replace(revision=None) sequential.children.append(private_location_no_draft.url()) - module_store.update_item(sequential, 'user') + module_store.update_item(sequential, self.user.id) # read back the sequential, to make sure we have a pointer to sequential = module_store.get_item(Location(['i4x', 'edX', 'toy', @@ -1766,7 +1766,7 @@ class ContentStoreTest(ModuleStoreTestCase): module_store.create_and_save_xmodule(new_component_location) parent = verticals[0] parent.children.append(new_component_location.url()) - module_store.update_item(parent, 'user') + module_store.update_item(parent, self.user.id) # flush the cache module_store.refresh_cached_metadata_inheritance_tree(new_component_location) @@ -1783,7 +1783,7 @@ class ContentStoreTest(ModuleStoreTestCase): # now let's define an override at the leaf node level # new_module.graceperiod = timedelta(1) - module_store.update_item(new_module, self.user.username) + module_store.update_item(new_module, self.user.id) # flush the cache and refetch module_store.refresh_cached_metadata_inheritance_tree(new_component_location) @@ -1897,7 +1897,7 @@ class MetadataSaveTestCase(ModuleStoreTestCase): delattr(self.video_descriptor, field_name) self.assertNotIn('html5_sources', own_metadata(self.video_descriptor)) - get_modulestore(location).update_item(self.video_descriptor, 'testuser') + get_modulestore(location).update_item(self.video_descriptor, '**replace_user**') module = get_modulestore(location).get_item(location) self.assertNotIn('html5_sources', own_metadata(module)) diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py index bfe244820d..e6cae27619 100644 --- a/cms/djangoapps/contentstore/tests/test_course_settings.py +++ b/cms/djangoapps/contentstore/tests/test_course_settings.py @@ -73,32 +73,32 @@ class CourseDetailsTestCase(CourseTestCase): jsondetails.syllabus = "bar" # encode - decode to convert date fields and other data which changes form self.assertEqual( - CourseDetails.update_from_json(self.course_locator, jsondetails.__dict__).syllabus, + CourseDetails.update_from_json(self.course_locator, jsondetails.__dict__, self.user).syllabus, jsondetails.syllabus, "After set syllabus" ) jsondetails.overview = "Overview" self.assertEqual( - CourseDetails.update_from_json(self.course_locator, jsondetails.__dict__).overview, + CourseDetails.update_from_json(self.course_locator, jsondetails.__dict__, self.user).overview, jsondetails.overview, "After set overview" ) jsondetails.intro_video = "intro_video" self.assertEqual( - CourseDetails.update_from_json(self.course_locator, jsondetails.__dict__).intro_video, + CourseDetails.update_from_json(self.course_locator, jsondetails.__dict__, self.user).intro_video, jsondetails.intro_video, "After set intro_video" ) jsondetails.effort = "effort" self.assertEqual( - CourseDetails.update_from_json(self.course_locator, jsondetails.__dict__).effort, + CourseDetails.update_from_json(self.course_locator, jsondetails.__dict__, self.user).effort, jsondetails.effort, "After set effort" ) jsondetails.start_date = datetime.datetime(2010, 10, 1, 0, tzinfo=UTC()) self.assertEqual( - CourseDetails.update_from_json(self.course_locator, jsondetails.__dict__).start_date, + CourseDetails.update_from_json(self.course_locator, jsondetails.__dict__, self.user).start_date, jsondetails.start_date ) jsondetails.course_image_name = "an_image.jpg" self.assertEqual( - CourseDetails.update_from_json(self.course_locator, jsondetails.__dict__).course_image_name, + CourseDetails.update_from_json(self.course_locator, jsondetails.__dict__, self.user).course_image_name, jsondetails.course_image_name ) @@ -241,67 +241,72 @@ class CourseGradingTest(CourseTestCase): def test_update_from_json(self): test_grader = CourseGradingModel.fetch(self.course_locator) - altered_grader = CourseGradingModel.update_from_json(self.course_locator, test_grader.__dict__) + altered_grader = CourseGradingModel.update_from_json(self.course_locator, test_grader.__dict__, self.user) self.assertDictEqual(test_grader.__dict__, altered_grader.__dict__, "Noop update") test_grader.graders[0]['weight'] = test_grader.graders[0].get('weight') * 2 - altered_grader = CourseGradingModel.update_from_json(self.course_locator, test_grader.__dict__) + altered_grader = CourseGradingModel.update_from_json(self.course_locator, test_grader.__dict__, self.user) self.assertDictEqual(test_grader.__dict__, altered_grader.__dict__, "Weight[0] * 2") test_grader.grade_cutoffs['D'] = 0.3 - altered_grader = CourseGradingModel.update_from_json(self.course_locator, test_grader.__dict__) + altered_grader = CourseGradingModel.update_from_json(self.course_locator, test_grader.__dict__, self.user) self.assertDictEqual(test_grader.__dict__, altered_grader.__dict__, "cutoff add D") test_grader.grace_period = {'hours': 4, 'minutes': 5, 'seconds': 0} - altered_grader = CourseGradingModel.update_from_json(self.course_locator, test_grader.__dict__) + altered_grader = CourseGradingModel.update_from_json(self.course_locator, test_grader.__dict__, self.user) self.assertDictEqual(test_grader.__dict__, altered_grader.__dict__, "4 hour grace period") def test_update_grader_from_json(self): test_grader = CourseGradingModel.fetch(self.course_locator) - altered_grader = CourseGradingModel.update_grader_from_json(self.course_locator, test_grader.graders[1]) + altered_grader = CourseGradingModel.update_grader_from_json( + self.course_locator, test_grader.graders[1], self.user) self.assertDictEqual(test_grader.graders[1], altered_grader, "Noop update") test_grader.graders[1]['min_count'] = test_grader.graders[1].get('min_count') + 2 - altered_grader = CourseGradingModel.update_grader_from_json(self.course_locator, test_grader.graders[1]) + altered_grader = CourseGradingModel.update_grader_from_json( + self.course_locator, test_grader.graders[1], self.user) self.assertDictEqual(test_grader.graders[1], altered_grader, "min_count[1] + 2") test_grader.graders[1]['drop_count'] = test_grader.graders[1].get('drop_count') + 1 - altered_grader = CourseGradingModel.update_grader_from_json(self.course_locator, test_grader.graders[1]) + altered_grader = CourseGradingModel.update_grader_from_json( + self.course_locator, test_grader.graders[1], self.user) self.assertDictEqual(test_grader.graders[1], altered_grader, "drop_count[1] + 2") def test_update_cutoffs_from_json(self): test_grader = CourseGradingModel.fetch(self.course_locator) - CourseGradingModel.update_cutoffs_from_json(self.course_locator, test_grader.grade_cutoffs) + CourseGradingModel.update_cutoffs_from_json(self.course_locator, test_grader.grade_cutoffs, self.user) # Unlike other tests, need to actually perform a db fetch for this test since update_cutoffs_from_json # simply returns the cutoffs you send into it, rather than returning the db contents. altered_grader = CourseGradingModel.fetch(self.course_locator) self.assertDictEqual(test_grader.grade_cutoffs, altered_grader.grade_cutoffs, "Noop update") test_grader.grade_cutoffs['D'] = 0.3 - CourseGradingModel.update_cutoffs_from_json(self.course_locator, test_grader.grade_cutoffs) + CourseGradingModel.update_cutoffs_from_json(self.course_locator, test_grader.grade_cutoffs, self.user) altered_grader = CourseGradingModel.fetch(self.course_locator) self.assertDictEqual(test_grader.grade_cutoffs, altered_grader.grade_cutoffs, "cutoff add D") test_grader.grade_cutoffs['Pass'] = 0.75 - CourseGradingModel.update_cutoffs_from_json(self.course_locator, test_grader.grade_cutoffs) + CourseGradingModel.update_cutoffs_from_json(self.course_locator, test_grader.grade_cutoffs, self.user) altered_grader = CourseGradingModel.fetch(self.course_locator) self.assertDictEqual(test_grader.grade_cutoffs, altered_grader.grade_cutoffs, "cutoff change 'Pass'") def test_delete_grace_period(self): test_grader = CourseGradingModel.fetch(self.course_locator) - CourseGradingModel.update_grace_period_from_json(self.course_locator, test_grader.grace_period) + CourseGradingModel.update_grace_period_from_json( + self.course_locator, test_grader.grace_period, self.user) # update_grace_period_from_json doesn't return anything, so query the db for its contents. altered_grader = CourseGradingModel.fetch(self.course_locator) self.assertEqual(test_grader.grace_period, altered_grader.grace_period, "Noop update") test_grader.grace_period = {'hours': 15, 'minutes': 5, 'seconds': 30} - CourseGradingModel.update_grace_period_from_json(self.course_locator, test_grader.grace_period) + CourseGradingModel.update_grace_period_from_json( + self.course_locator, test_grader.grace_period, self.user) altered_grader = CourseGradingModel.fetch(self.course_locator) self.assertDictEqual(test_grader.grace_period, altered_grader.grace_period, "Adding in a grace period") test_grader.grace_period = {'hours': 1, 'minutes': 10, 'seconds': 0} # Now delete the grace period - CourseGradingModel.delete_grace_period(self.course_locator) + CourseGradingModel.delete_grace_period(self.course_locator, self.user) # update_grace_period_from_json doesn't return anything, so query the db for its contents. altered_grader = CourseGradingModel.fetch(self.course_locator) # Once deleted, the grace period should simply be None @@ -317,7 +322,7 @@ class CourseGradingTest(CourseTestCase): self.assertEqual(False, descriptor.graded) # Change the default grader type to Homework, which should also mark the section as graded - CourseGradingModel.update_section_grader_type(self.course, 'Homework') + CourseGradingModel.update_section_grader_type(self.course, 'Homework', self.user) descriptor = get_modulestore(self.course.location).get_item(self.course.location) section_grader_type = CourseGradingModel.get_section_grader_type(self.course_locator) @@ -326,7 +331,7 @@ class CourseGradingTest(CourseTestCase): self.assertEqual(True, descriptor.graded) # Change the grader type back to notgraded, which should also unmark the section as graded - CourseGradingModel.update_section_grader_type(self.course, 'notgraded') + CourseGradingModel.update_section_grader_type(self.course, 'notgraded', self.user) descriptor = get_modulestore(self.course.location).get_item(self.course.location) section_grader_type = CourseGradingModel.get_section_grader_type(self.course_locator) @@ -439,19 +444,25 @@ class CourseMetadataEditingTest(CourseTestCase): self.assertIn('xqa_key', test_model, 'xqa_key field ') def test_update_from_json(self): - test_model = CourseMetadata.update_from_json(self.course, { - "advertised_start": "start A", - "days_early_for_beta": 2 - }) + test_model = CourseMetadata.update_from_json( + self.course, { + "advertised_start": "start A", + "days_early_for_beta": 2 + }, + user=self.user + ) self.update_check(test_model) # try fresh fetch to ensure persistence fresh = modulestore().get_item(self.course_location) test_model = CourseMetadata.fetch(fresh) self.update_check(test_model) # now change some of the existing metadata - test_model = CourseMetadata.update_from_json(fresh, { - "advertised_start": "start B", - "display_name": "jolly roger"} + test_model = CourseMetadata.update_from_json( + fresh, { + "advertised_start": "start B", + "display_name": "jolly roger" + }, + user=self.user ) self.assertIn('display_name', test_model, 'Missing editable metadata field') self.assertEqual(test_model['display_name'], 'jolly roger', "not expected value") @@ -470,7 +481,8 @@ class CourseMetadataEditingTest(CourseTestCase): test_model = CourseMetadata.update_from_json( self.fullcourse, { "unsetKeys": ['showanswer', 'xqa_key'] - } + }, + user=self.user ) # ensure no harm self.assertNotIn('graceperiod', test_model, 'blacklisted field leaked in') diff --git a/cms/djangoapps/contentstore/tests/test_course_updates.py b/cms/djangoapps/contentstore/tests/test_course_updates.py index 1a112f87e1..38b24d9f53 100644 --- a/cms/djangoapps/contentstore/tests/test_course_updates.py +++ b/cms/djangoapps/contentstore/tests/test_course_updates.py @@ -123,7 +123,7 @@ class CourseUpdateTest(CourseTestCase): modulestore('direct').create_and_save_xmodule(location) course_updates = modulestore('direct').get_item(location) course_updates.data = 'bad news' - modulestore('direct').update_item(course_updates, 'test_course_updates') + modulestore('direct').update_item(course_updates, self.user.id) init_content = '' diff --git a/cms/djangoapps/contentstore/tests/test_crud.py b/cms/djangoapps/contentstore/tests/test_crud.py index 6094c7cf3b..290b90e4bc 100644 --- a/cms/djangoapps/contentstore/tests/test_crud.py +++ b/cms/djangoapps/contentstore/tests/test_crud.py @@ -172,7 +172,7 @@ class TemplateTests(unittest.TestCase): ) first_problem.max_attempts = 3 first_problem.save() # decache the above into the kvs - updated_problem = modulestore('split').update_item(first_problem, 'testbot') + updated_problem = modulestore('split').update_item(first_problem, '**replace_user**') self.assertIsNotNone(updated_problem.previous_version) self.assertEqual(updated_problem.previous_version, first_problem.update_version) self.assertNotEqual(updated_problem.update_version, first_problem.update_version) diff --git a/cms/djangoapps/contentstore/tests/test_orphan.py b/cms/djangoapps/contentstore/tests/test_orphan.py index 3585d81e15..0bdcb69bbc 100644 --- a/cms/djangoapps/contentstore/tests/test_orphan.py +++ b/cms/djangoapps/contentstore/tests/test_orphan.py @@ -34,7 +34,7 @@ class TestOrphan(CourseTestCase): parent_location = self.course.location.replace(category=parent_category, name=parent_name) parent = editable_modulestore('direct').get_item(parent_location) parent.children.append(location.url()) - editable_modulestore('direct').update_item(parent, self.user.pk) + editable_modulestore('direct').update_item(parent, self.user.id) def test_mongo_orphan(self): """ diff --git a/cms/djangoapps/contentstore/tests/test_textbooks.py b/cms/djangoapps/contentstore/tests/test_textbooks.py index aab4ccc399..7296ab851a 100644 --- a/cms/djangoapps/contentstore/tests/test_textbooks.py +++ b/cms/djangoapps/contentstore/tests/test_textbooks.py @@ -59,7 +59,7 @@ class TextbookIndexTestCase(CourseTestCase): ] self.course.pdf_textbooks = content store = get_modulestore(self.course.location) - store.update_item(self.course, self.user.pk) + store.update_item(self.course, self.user.id) resp = self.client.get( self.url, @@ -197,7 +197,7 @@ class TextbookDetailTestCase(CourseTestCase): # MongoKeyValueStore before we update the mongo datastore. self.course.save() self.store = get_modulestore(self.course.location) - self.store.update_item(self.course, self.user.pk) + self.store.update_item(self.course, self.user.id) self.url_nonexist = self.course_locator.url_reverse("textbooks", "20") def test_get_1(self): diff --git a/cms/djangoapps/contentstore/tests/test_transcripts.py b/cms/djangoapps/contentstore/tests/test_transcripts.py index 57e30ed9db..138b60b513 100644 --- a/cms/djangoapps/contentstore/tests/test_transcripts.py +++ b/cms/djangoapps/contentstore/tests/test_transcripts.py @@ -67,7 +67,7 @@ class Basetranscripts(CourseTestCase): # hI10vDNYz4M - valid Youtube ID with transcripts. # JMD_ifUUfsU, AKqURZnYqpk, DYpADpL7jAY - valid Youtube IDs without transcripts. self.item.data = ' """) - modulestore().update_item(self.item, 'test_transcripts') + modulestore().update_item(self.item, self.user.id) link = reverse('upload_transcripts') filename = os.path.splitext(os.path.basename(self.good_srt_file.name))[0] @@ -214,7 +214,7 @@ class TestUploadtranscripts(Basetranscripts): item_locator, item_location = self._get_locator(resp) item = modulestore().get_item(item_location) item.data = '' - modulestore().update_item(item, 'test_transcripts') + modulestore().update_item(item, self.user.id) # non_video module: testing @@ -234,7 +234,7 @@ class TestUploadtranscripts(Basetranscripts): def test_fail_bad_xml(self): self.item.data = '<< """) - modulestore().update_item(self.item, 'test_transcripts') + modulestore().update_item(self.item, self.user.id) link = reverse('download_transcripts') resp = self.client.get(link, {'locator': self.item_locator}) @@ -472,7 +472,7 @@ class TestDownloadtranscripts(Basetranscripts): """) - modulestore().update_item(self.item, 'test_transcripts') + modulestore().update_item(self.item, self.user.id) link = reverse('download_transcripts') resp = self.client.get(link, {'locator': self.item_locator}) @@ -488,7 +488,7 @@ class TestDownloadtranscripts(Basetranscripts): """.format(subs_id)) - modulestore().update_item(self.item, 'test_transcripts') + modulestore().update_item(self.item, self.user.id) subs = { 'start': [100, 200, 240], @@ -541,7 +541,7 @@ class TestChecktranscripts(Basetranscripts): """.format(subs_id)) - modulestore().update_item(self.item, 'test_transcripts') + modulestore().update_item(self.item, self.user.id) subs = { 'start': [100, 200, 240], @@ -585,7 +585,7 @@ class TestChecktranscripts(Basetranscripts): def test_check_youtube(self): self.item.data = '