From f7e78544dea4a8885af9f2274c7a22b0b41e6dba Mon Sep 17 00:00:00 2001 From: zubiar-arbi Date: Wed, 12 Feb 2014 19:48:06 +0500 Subject: [PATCH 1/2] failing test for xblock_handler STUD-1311 --- .../contentstore/tests/test_item.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/cms/djangoapps/contentstore/tests/test_item.py b/cms/djangoapps/contentstore/tests/test_item.py index 238660f510..376f8ff82e 100644 --- a/cms/djangoapps/contentstore/tests/test_item.py +++ b/cms/djangoapps/contentstore/tests/test_item.py @@ -538,6 +538,41 @@ class TestEditItem(ItemTest): draft = self.get_item_from_modulestore(self.problem_locator, True) self.assertEqual(draft.due, datetime(2077, 10, 10, 4, 0, tzinfo=UTC)) + def test_published_and_draft_contents_with_update(self): + """ Create a draft and publish it then modify the draft and check that published content is not modified """ + + # Make problem public. + resp = self.client.ajax_post( + self.problem_update_url, + data={'publish': 'make_public'} + ) + self.assertIsNotNone(self.get_item_from_modulestore(self.problem_locator, False)) + + # Now make a draft + resp = self.client.ajax_post( + self.problem_update_url, + data={ + 'id': self.problem_locator, + 'metadata': {}, + 'data': "

Problem content draft.

", + 'publish': 'create_draft' + } + ) + + # Both published and draft content should be different + published = self.get_item_from_modulestore(self.problem_locator, False) + draft = self.get_item_from_modulestore(self.problem_locator, True) + self.assertNotEqual(draft.data, published.data) + + # Get problem by 'xblock_handler' + resp = self.client.get('/xblock/' + self.problem_locator, HTTP_ACCEPT='application/x-fragment+json') + self.assertEqual(resp.status_code, 200) + + # Both published and draft content should still be different + published = self.get_item_from_modulestore(self.problem_locator, False) + draft = self.get_item_from_modulestore(self.problem_locator, True) + self.assertNotEqual(draft.data, published.data) + @ddt.ddt class TestComponentHandler(TestCase): From 4403eb720937d96164790e4a0227a2c27db078c8 Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Wed, 12 Feb 2014 10:25:01 -0500 Subject: [PATCH 2/2] Fix STUD-1311 (Don't overwrite published content w/ draft content accidentally) --- cms/djangoapps/contentstore/views/item.py | 5 +++-- .../lib/xmodule/xmodule/modulestore/mongo/draft.py | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py index 8d80d9e0bb..dfb5fd5704 100644 --- a/cms/djangoapps/contentstore/views/item.py +++ b/cms/djangoapps/contentstore/views/item.py @@ -112,7 +112,8 @@ def xblock_handler(request, tag=None, package_id=None, branch=None, version_guid accept_header = request.META.get('HTTP_ACCEPT', 'application/json') if 'application/x-fragment+json' in accept_header: - component = modulestore().get_item(old_location) + store = get_modulestore(old_location) + component = store.get_item(old_location) # Wrap the generated fragment in the xmodule_editor div so that the javascript # can bind to it correctly @@ -127,7 +128,7 @@ def xblock_handler(request, tag=None, package_id=None, branch=None, version_guid log.debug("Unable to render studio_view for %r", component, exc_info=True) editor_fragment = Fragment(render_to_string('html_error.html', {'message': str(exc)})) - modulestore().save_xmodule(component) + store.save_xmodule(component) preview_fragment = get_preview_fragment(request, component) diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py index f7a0250155..7ebc7a5a05 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py @@ -108,6 +108,20 @@ class DraftModuleStore(MongoModuleStore): raise InvalidVersionError(location) return super(DraftModuleStore, self).create_xmodule(draft_loc, definition_data, metadata, system) + def save_xmodule(self, xmodule): + """ + Save the given xmodule (will either create or update based on whether id already exists). + Pulls out the data definition v metadata v children locally but saves it all. + + :param xmodule: + """ + orig_location = xmodule.location + + xmodule.location = as_draft(orig_location) + try: + super(DraftModuleStore, self).save_xmodule(xmodule) + finally: + xmodule.location = orig_location def get_items(self, location, course_id=None, depth=0): """