Commit b24c2280 by Calen Pennington Committed by GitHub

Merge pull request #14047 from cpennington/safer-opaque-keys

Safer opaque keys
parents d2b6c9eb 42617545
......@@ -22,6 +22,7 @@ course.certificates: {
}
"""
import json
import logging
from django.conf import settings
from django.contrib.auth.decorators import login_required
......@@ -33,6 +34,7 @@ from django.views.decorators.http import require_http_methods
from contentstore.utils import reverse_course_url
from edxmako.shortcuts import render_to_response
from opaque_keys.edx.keys import CourseKey, AssetKey
from opaque_keys import InvalidKeyError
from eventtracking import tracker
from student.auth import has_studio_write_access
from student.roles import GlobalStaff
......@@ -49,6 +51,8 @@ from contentstore.utils import get_lms_link_for_certificate_web_view
CERTIFICATE_SCHEMA_VERSION = 1
CERTIFICATE_MINIMUM_ID = 100
LOGGER = logging.getLogger(__name__)
def _get_course_and_check_access(course_key, user, depth=0):
"""
......@@ -67,11 +71,32 @@ def _delete_asset(course_key, asset_key_string):
remove asset by calling delete_asset method of assets module.
"""
if asset_key_string:
# remove first slash in asset path
# otherwise it generates InvalidKeyError in case of split modulestore
if '/' == asset_key_string[0]:
asset_key_string = asset_key_string[1:]
asset_key = AssetKey.from_string(asset_key_string)
try:
asset_key = AssetKey.from_string(asset_key_string)
except InvalidKeyError:
# remove first slash in asset path
# otherwise it generates InvalidKeyError in case of split modulestore
if '/' == asset_key_string[0]:
asset_key_string = asset_key_string[1:]
try:
asset_key = AssetKey.from_string(asset_key_string)
except InvalidKeyError:
# Unable to parse the asset key, log and return
LOGGER.info(
"In course %r, unable to parse asset key %r, not attempting to delete signatory.",
course_key,
asset_key_string,
)
return
else:
# Unable to parse the asset key, log and return
LOGGER.info(
"In course %r, unable to parse asset key %r, not attempting to delete signatory.",
course_key,
asset_key_string,
)
return
try:
delete_asset(course_key, asset_key)
# If the asset was not found, it doesn't have to be deleted...
......
......@@ -21,7 +21,7 @@ from xmodule.services import SettingsService
from xmodule.modulestore.django import modulestore, ModuleI18nService
from xmodule.mixin import wrap_with_license
from opaque_keys.edx.keys import UsageKey
from opaque_keys.edx.asides import AsideUsageKeyV1
from opaque_keys.edx.asides import AsideUsageKeyV1, AsideUsageKeyV2
from xmodule.x_module import ModuleSystem
from xblock.runtime import KvsFieldData
from xblock.django.request import webob_to_django_response, django_to_webob_request
......@@ -57,7 +57,7 @@ def preview_handler(request, usage_key_string, handler, suffix=''):
"""
usage_key = UsageKey.from_string(usage_key_string)
if isinstance(usage_key, AsideUsageKeyV1):
if isinstance(usage_key, (AsideUsageKeyV1, AsideUsageKeyV2)):
descriptor = modulestore().get_item(usage_key.usage_key)
for aside in descriptor.runtime.get_asides(descriptor):
if aside.scope_ids.block_type == usage_key.aside_type:
......
......@@ -2,6 +2,7 @@
Tests for the Studio Tagging XBlockAside
"""
import ddt
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
......@@ -17,13 +18,14 @@ from contentstore.utils import reverse_usage_url
from contentstore.tests.utils import AjaxEnabledTestClient
from django.test.client import RequestFactory
from student.tests.factories import UserFactory
from opaque_keys.edx.asides import AsideUsageKeyV1
from opaque_keys.edx.asides import AsideUsageKeyV1, AsideUsageKeyV2
from datetime import datetime
from pytz import UTC
from lxml import etree
from StringIO import StringIO
@ddt.ddt
class StructuredTagsAsideTestCase(ModuleStoreTestCase):
"""
Base class for tests of StructuredTagsAside (tagging.py)
......@@ -179,13 +181,14 @@ class StructuredTagsAsideTestCase(ModuleStoreTestCase):
video_html = get_preview_fragment(request, self.video, context).content
self.assertNotRegexpMatches(video_html, "<select")
def test_handle_requests(self):
@ddt.data(AsideUsageKeyV1, AsideUsageKeyV2)
def test_handle_requests(self, aside_key_class):
"""
Checks that handler to save tags in StructuredTagsAside works properly
"""
handler_url = reverse_usage_url(
'preview_handler',
'%s:%s::%s' % (AsideUsageKeyV1.CANONICAL_NAMESPACE, self.problem.location, self.aside_name),
unicode(aside_key_class(self.problem.location, self.aside_name)),
kwargs={'handler': 'save_tags'}
)
......
......@@ -55,7 +55,7 @@ setup(
'capa',
'path.py',
'webob',
'edx-opaque-keys>=0.3.4,<1.0.0',
'edx-opaque-keys>=0.4.0,<1.0.0',
],
package_data={
'xmodule': ['js/module/*'],
......
......@@ -200,7 +200,10 @@ class StaticContent(object):
if path.startswith('/static/'):
path = path[len('/static/'):]
path = path.lstrip('/')
# Old-style asset keys start with `/`, so don't try and strip it
# in that case.
if not path.startswith('/c4x'):
path = path.lstrip('/')
try:
return AssetKey.from_string(path)
......
......@@ -33,7 +33,7 @@ from xmodule.errortracker import exc_info_to_str
from xmodule.modulestore.exceptions import ItemNotFoundError
from opaque_keys.edx.keys import UsageKey
from opaque_keys.edx.asides import AsideUsageKeyV1, AsideDefinitionKeyV1
from opaque_keys.edx.asides import AsideUsageKeyV2, AsideDefinitionKeyV2
from xmodule.exceptions import UndefinedContext
import dogstats_wrapper as dog_stats_api
......@@ -155,8 +155,8 @@ class AsideKeyGenerator(IdGenerator):
Returns:
(aside_definition_id, aside_usage_id)
"""
def_key = AsideDefinitionKeyV1(definition_id, aside_type)
usage_key = AsideUsageKeyV1(usage_id, aside_type)
def_key = AsideDefinitionKeyV2(definition_id, aside_type)
usage_key = AsideUsageKeyV2(usage_id, aside_type)
return (def_key, usage_key)
def create_usage(self, def_id):
......
......@@ -33,7 +33,7 @@ from .models import (
import logging
from opaque_keys.edx.keys import CourseKey, UsageKey
from opaque_keys.edx.block_types import BlockTypeKeyV1
from opaque_keys.edx.asides import AsideUsageKeyV1
from opaque_keys.edx.asides import AsideUsageKeyV1, AsideUsageKeyV2
from contracts import contract, new_contract
from django.db import DatabaseError
......@@ -67,6 +67,7 @@ def _all_usage_keys(descriptors, aside_types):
for aside_type in aside_types:
usage_ids.add(AsideUsageKeyV1(descriptor.scope_ids.usage_id, aside_type))
usage_ids.add(AsideUsageKeyV2(descriptor.scope_ids.usage_id, aside_type))
return usage_ids
......
......@@ -26,7 +26,6 @@ __test__ = False # do not collect
@cmdopts([
("system=", "s", "System to act on"),
("test-id=", "t", "Test id"),
("failed", "f", "Run only failed tests"),
("fail-fast", "x", "Fail suite on first failed test"),
("fasttest", "a", "Run without collectstatic"),
make_option(
......
......@@ -48,7 +48,7 @@ edx-django-oauth2-provider==1.1.4
edx-django-sites-extensions==2.1.1
edx-enterprise==0.1.0
edx-oauth2-provider==1.2.0
edx-opaque-keys==0.3.4
edx-opaque-keys==0.4.0
edx-organizations==0.4.1
edx-rest-api-client==1.2.1
edx-search==0.1.2
......
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