Skip to content

Commit a2cfb06

Browse files
committed
Revert "feat: add support for lct in library_context"
This reverts commit 72ba6ef.
1 parent e8a8d58 commit a2cfb06

File tree

5 files changed

+57
-151
lines changed

5 files changed

+57
-151
lines changed

openedx/core/djangoapps/content_libraries/library_context.py

Lines changed: 27 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
from openedx_events.content_authoring.data import LibraryBlockData, LibraryContainerData
1010
from openedx_events.content_authoring.signals import LIBRARY_BLOCK_UPDATED, LIBRARY_CONTAINER_UPDATED
11-
from opaque_keys.edx.keys import UsageKeyV2, OpaqueKey
12-
from opaque_keys.edx.locator import LibraryContainerLocator, LibraryLocatorV2, LibraryUsageLocatorV2
11+
from opaque_keys.edx.keys import UsageKeyV2
12+
from opaque_keys.edx.locator import LibraryUsageLocatorV2, LibraryLocatorV2
1313
from openedx_learning.api import authoring as authoring_api
1414

1515
from openedx.core.djangoapps.content_libraries import api, permissions
@@ -20,63 +20,50 @@
2020
log = logging.getLogger(__name__)
2121

2222

23-
class LibraryContextPermissionBase:
24-
locator_type = OpaqueKey
23+
class LibraryContextImpl(LearningContext):
24+
"""
25+
Implements content libraries as a learning context.
26+
27+
This is the *new* content libraries based on Learning Core, not the old content
28+
libraries based on modulestore.
29+
"""
2530

2631
def __init__(self, **kwargs):
2732
super().__init__(**kwargs)
2833
self.use_draft = kwargs.get('use_draft', None)
2934

30-
def get_library_key(self, opaque_key: OpaqueKey):
35+
def can_edit_block(self, user: UserType, usage_key: UsageKeyV2) -> bool:
3136
"""
32-
Get library key from given opaque_key.
33-
"""
34-
raise NotImplementedError()
35-
36-
def can_edit_block(self, user: UserType, opaque_key: OpaqueKey) -> bool:
37-
"""
38-
Assuming a block with the specified ID (opaque_key) exists, does the
37+
Assuming a block with the specified ID (usage_key) exists, does the
3938
specified user have permission to edit it (make changes to the
4039
fields / authored data store)?
4140
4241
May raise ContentLibraryNotFound if the library does not exist.
4342
"""
44-
assert isinstance(opaque_key, self.locator_type)
45-
return self._check_perm(
46-
user,
47-
self.get_library_key(opaque_key),
48-
permissions.CAN_EDIT_THIS_CONTENT_LIBRARY
49-
)
43+
assert isinstance(usage_key, LibraryUsageLocatorV2)
44+
return self._check_perm(user, usage_key.lib_key, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY)
5045

51-
def can_view_block_for_editing(self, user: UserType, opaque_key: OpaqueKey) -> bool:
46+
def can_view_block_for_editing(self, user: UserType, usage_key: UsageKeyV2) -> bool:
5247
"""
53-
Assuming a block with the specified ID (opaque_key) exists, does the
48+
Assuming a block with the specified ID (usage_key) exists, does the
5449
specified user have permission to view its fields and OLX details (but
5550
not necessarily to make changes to it)?
5651
5752
May raise ContentLibraryNotFound if the library does not exist.
5853
"""
59-
assert isinstance(opaque_key, self.locator_type)
60-
return self._check_perm(
61-
user,
62-
self.get_library_key(opaque_key),
63-
permissions.CAN_VIEW_THIS_CONTENT_LIBRARY
64-
)
54+
assert isinstance(usage_key, LibraryUsageLocatorV2)
55+
return self._check_perm(user, usage_key.lib_key, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
6556

66-
def can_view_block(self, user: UserType, opaque_key: OpaqueKey) -> bool:
57+
def can_view_block(self, user: UserType, usage_key: UsageKeyV2) -> bool:
6758
"""
6859
Does the specified usage key exist in its context, and if so, does the
6960
specified user have permission to view it and interact with it (call
7061
handlers, save user state, etc.)?
7162
7263
May raise ContentLibraryNotFound if the library does not exist.
7364
"""
74-
assert isinstance(opaque_key, self.locator_type)
75-
return self._check_perm(
76-
user,
77-
self.get_library_key(opaque_key),
78-
permissions.CAN_LEARN_FROM_THIS_CONTENT_LIBRARY
79-
)
65+
assert isinstance(usage_key, LibraryUsageLocatorV2)
66+
return self._check_perm(user, usage_key.lib_key, permissions.CAN_LEARN_FROM_THIS_CONTENT_LIBRARY)
8067

8168
def _check_perm(self, user: UserType, lib_key: LibraryLocatorV2, perm) -> bool:
8269
""" Helper method to check a permission for the various can_ methods"""
@@ -89,23 +76,6 @@ def _check_perm(self, user: UserType, lib_key: LibraryLocatorV2, perm) -> bool:
8976
# A 404 is probably what you want in this case, not a 500 error, so do that by default.
9077
raise NotFound(f"Content Library '{lib_key}' does not exist") from exc
9178

92-
93-
class LibraryContextImpl(LibraryContextPermissionBase, LearningContext):
94-
"""
95-
Implements content libraries as a learning context.
96-
97-
This is the *new* content libraries based on Learning Core, not the old content
98-
libraries based on modulestore.
99-
"""
100-
101-
locator_type = LibraryUsageLocatorV2
102-
103-
def get_library_key(self, opaque_key: OpaqueKey):
104-
"""
105-
Get library key from given opaque_key.
106-
"""
107-
return opaque_key.lib_key
108-
10979
def block_exists(self, usage_key: LibraryUsageLocatorV2):
11080
"""
11181
Does the block for this usage_key exist in this Library?
@@ -133,82 +103,29 @@ def block_exists(self, usage_key: LibraryUsageLocatorV2):
133103
local_key=usage_key.block_id,
134104
)
135105

136-
def send_block_updated_event(self, opaque_key: OpaqueKey):
106+
def send_block_updated_event(self, usage_key: UsageKeyV2):
137107
"""
138108
Send a "block updated" event for the library block with the given usage_key.
139109
"""
140-
assert isinstance(opaque_key, self.locator_type)
110+
assert isinstance(usage_key, LibraryUsageLocatorV2)
141111
LIBRARY_BLOCK_UPDATED.send_event(
142112
library_block=LibraryBlockData(
143-
library_key=opaque_key.lib_key,
144-
usage_key=opaque_key,
113+
library_key=usage_key.lib_key,
114+
usage_key=usage_key,
145115
)
146116
)
147117

148-
def send_container_updated_events(self, opaque_key: OpaqueKey):
118+
def send_container_updated_events(self, usage_key: UsageKeyV2):
149119
"""
150120
Send "container updated" events for containers that contains the library block
151121
with the given usage_key.
152122
"""
153-
assert isinstance(opaque_key, self.locator_type)
154-
affected_containers = api.get_containers_contains_component(opaque_key)
123+
assert isinstance(usage_key, LibraryUsageLocatorV2)
124+
affected_containers = api.get_containers_contains_component(usage_key)
155125
for container in affected_containers:
156126
LIBRARY_CONTAINER_UPDATED.send_event(
157127
library_container=LibraryContainerData(
158128
container_key=container.container_key,
159129
background=True,
160130
)
161131
)
162-
163-
164-
class LibraryContextContainerImpl(LibraryContextPermissionBase, LearningContext):
165-
"""
166-
Implements content libraries as a learning context for containers in libraries.
167-
168-
This is the *new* content libraries based on Learning Core, not the old content
169-
libraries based on modulestore.
170-
"""
171-
172-
locator_type = LibraryContainerLocator
173-
174-
def get_library_key(self, opaque_key: OpaqueKey):
175-
"""
176-
Get library key from given opaque_key.
177-
"""
178-
return opaque_key.library_key
179-
180-
def container_exists(self, container_key: LibraryContainerLocator):
181-
"""
182-
Does the container for this key exist in this Library?
183-
184-
Note that this applies to all versions, i.e. you can put a container key for
185-
a piece of content that has been soft-deleted (removed from Drafts), and
186-
it will still return True here. That's because for the purposes of
187-
permission checking, we just want to know whether that block has ever
188-
existed in this Library, because we could be looking at any older
189-
version of it.
190-
"""
191-
try:
192-
content_lib = ContentLibrary.objects.get_by_key(container_key.library_key) # type: ignore[attr-defined]
193-
except ContentLibrary.DoesNotExist:
194-
return False
195-
196-
learning_package = content_lib.learning_package
197-
if learning_package is None:
198-
return False
199-
200-
return authoring_api.container_exists_by_key(
201-
learning_package.id,
202-
container_key,
203-
)
204-
205-
def send_block_updated_event(self, opaque_key: OpaqueKey):
206-
"""
207-
Send a "block updated" event for the library block with the given usage_key.
208-
"""
209-
assert isinstance(opaque_key, self.locator_type)
210-
LIBRARY_CONTAINER_UPDATED.send_event(
211-
library_container=LibraryContainerData(
212-
container_key=opaque_key,
213-
)
214-
)

openedx/core/djangoapps/content_staging/views.py

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import edx_api_doc_tools as apidocs
1111
from opaque_keys import InvalidKeyError
1212
from opaque_keys.edx.keys import UsageKey
13-
from opaque_keys.edx.locator import CourseLocator, LibraryContainerLocator, LibraryLocatorV2
13+
from opaque_keys.edx.locator import CourseLocator, LibraryLocatorV2
1414
from rest_framework.exceptions import NotFound, PermissionDenied, ValidationError
1515
from rest_framework.response import Response
1616
from rest_framework.views import APIView
@@ -85,18 +85,12 @@ def post(self, request):
8585
# Check if the content exists and the user has permission to read it.
8686
# Parse the usage key:
8787
try:
88-
opaque_key = UsageKey.from_string(request.data["usage_key"])
89-
if opaque_key.block_type in ('course', 'chapter', 'sequential'):
90-
raise ValidationError('Requested XBlock tree is too large')
91-
except InvalidKeyError:
92-
try:
93-
# Check if valid library container
94-
opaque_key = LibraryContainerLocator.from_string(request.data["usage_key"])
95-
if opaque_key.container_type != 'unit':
96-
raise ValidationError('Requested XBlock tree is too large')
97-
except (ValueError, InvalidKeyError):
98-
raise ValidationError('Invalid usage key') # lint-amnesty, pylint: disable=raise-missing-from
99-
course_key = getattr(opaque_key, 'context_key', None) or getattr(opaque_key, 'library_key', None)
88+
usage_key = UsageKey.from_string(request.data["usage_key"])
89+
except (ValueError, InvalidKeyError):
90+
raise ValidationError('Invalid usage key') # lint-amnesty, pylint: disable=raise-missing-from
91+
if usage_key.block_type in ('course', 'chapter', 'sequential'):
92+
raise ValidationError('Requested XBlock tree is too large')
93+
course_key = usage_key.context_key
10094

10195
# Load the block and copy it to the user's clipboard
10296
try:
@@ -106,7 +100,7 @@ def post(self, request):
106100
raise PermissionDenied(
107101
"You must be a member of the course team in Studio to export OLX using this API."
108102
)
109-
block = modulestore().get_item(opaque_key)
103+
block = modulestore().get_item(usage_key)
110104
version_num = None
111105

112106
elif isinstance(course_key, LibraryLocatorV2):
@@ -115,12 +109,8 @@ def post(self, request):
115109
request.user,
116110
lib_api.permissions.CAN_VIEW_THIS_CONTENT_LIBRARY
117111
)
118-
if isinstance(opaque_key, LibraryContainerLocator):
119-
# TODO: load unit block data to staging content, probably need to convert unit from library to xml
120-
raise NotImplementedError("Containers not supported yet")
121-
else:
122-
block = xblock_api.load_block(opaque_key, user=None)
123-
version_num = lib_api.get_library_block(opaque_key).draft_version_num
112+
block = xblock_api.load_block(usage_key, user=None)
113+
version_num = lib_api.get_library_block(usage_key).draft_version_num
124114

125115
else:
126116
raise ValidationError("Invalid usage_key for the content.")

openedx/core/djangoapps/xblock/learning_context/learning_context.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
of content where learning happens.
44
"""
55
from openedx.core.types import User as UserType
6-
from opaque_keys.edx.keys import OpaqueKey
6+
from opaque_keys.edx.keys import UsageKeyV2
77

88

99
class LearningContext:
@@ -25,62 +25,62 @@ def __init__(self, **kwargs):
2525
parameters without changing the API.
2626
"""
2727

28-
def can_edit_block(self, user: UserType, opaque_key: OpaqueKey) -> bool: # pylint: disable=unused-argument
28+
def can_edit_block(self, user: UserType, usage_key: UsageKeyV2) -> bool: # pylint: disable=unused-argument
2929
"""
30-
Assuming a block with the specified ID (opaque_key) exists, does the
30+
Assuming a block with the specified ID (usage_key) exists, does the
3131
specified user have permission to edit it (make changes to the
3232
fields / authored data store)?
3333
3434
user: a Django User object (may be an AnonymousUser)
3535
36-
opaque_key: the OpaqueKey subclass used for this learning context
36+
usage_key: the UsageKeyV2 subclass used for this learning context
3737
3838
Must return a boolean.
3939
"""
4040
return False
4141

42-
def can_view_block_for_editing(self, user: UserType, opaque_key: OpaqueKey) -> bool:
42+
def can_view_block_for_editing(self, user: UserType, usage_key: UsageKeyV2) -> bool:
4343
"""
44-
Assuming a block with the specified ID (opaque_key) exists, does the
44+
Assuming a block with the specified ID (usage_key) exists, does the
4545
specified user have permission to view its fields and OLX details (but
4646
not necessarily to make changes to it)?
4747
"""
48-
return self.can_edit_block(user, opaque_key)
48+
return self.can_edit_block(user, usage_key)
4949

50-
def can_view_block(self, user: UserType, opaque_key: OpaqueKey) -> bool: # pylint: disable=unused-argument
50+
def can_view_block(self, user: UserType, usage_key: UsageKeyV2) -> bool: # pylint: disable=unused-argument
5151
"""
52-
Assuming a block with the specified ID (opaque_key) exists, does the
52+
Assuming a block with the specified ID (usage_key) exists, does the
5353
specified user have permission to view it and interact with it (call
5454
handlers, save user state, etc.)? This is also sometimes called the
5555
"can_learn" permission.
5656
5757
user: a Django User object (may be an AnonymousUser)
5858
59-
opaque_key: the OpaqueKey subclass used for this learning context
59+
usage_key: the UsageKeyV2 subclass used for this learning context
6060
6161
Must return a boolean.
6262
"""
6363
return False
6464

65-
def definition_for_usage(self, opaque_key, **kwargs):
65+
def definition_for_usage(self, usage_key, **kwargs):
6666
"""
6767
Given a usage key in this context, return the key indicating the actual XBlock definition.
6868
6969
Retuns None if the usage key doesn't exist in this context.
7070
"""
7171
raise NotImplementedError
7272

73-
def send_block_updated_event(self, opaque_key):
73+
def send_block_updated_event(self, usage_key):
7474
"""
75-
Send a "block updated" event for the block with the given opaque_key in this context.
75+
Send a "block updated" event for the block with the given usage_key in this context.
7676
77-
opaque_key: the OpaqueKey subclass used for this learning context
77+
usage_key: the UsageKeyV2 subclass used for this learning context
7878
"""
7979

80-
def send_container_updated_events(self, opaque_key):
80+
def send_container_updated_events(self, usage_key):
8181
"""
8282
Send "container updated" events for containers that contains the block with
83-
the given opaque_key in this context.
83+
the given usage_key in this context.
8484
85-
opaque_key: the OpaqueKey subclass used for this learning context
85+
usage_key: the UsageKeyV2 subclass used for this learning context
8686
"""

openedx/core/djangoapps/xblock/learning_context/manager.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"""
44
from edx_django_utils.plugins import PluginManager
55
from opaque_keys import OpaqueKey
6-
from opaque_keys.edx.keys import LearningContextKey, LibraryItemKey, UsageKeyV2
6+
from opaque_keys.edx.keys import LearningContextKey, UsageKeyV2
77

88
from openedx.core.djangoapps.xblock.apps import get_xblock_app_config
99

@@ -33,8 +33,8 @@ def get_learning_context_impl(key):
3333
Raises PluginError if there is some misconfiguration causing the context
3434
implementation to not be installed.
3535
"""
36-
if isinstance(key, LearningContextKey) or isinstance(key, LibraryItemKey):
37-
context_type = key.CANONICAL_NAMESPACE # e.g. 'lib' or 'lct'
36+
if isinstance(key, LearningContextKey):
37+
context_type = key.CANONICAL_NAMESPACE # e.g. 'lib'
3838
elif isinstance(key, UsageKeyV2):
3939
context_type = key.context_key.CANONICAL_NAMESPACE
4040
elif isinstance(key, OpaqueKey):

setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,6 @@
181181
],
182182
'openedx.learning_context': [
183183
'lib = openedx.core.djangoapps.content_libraries.library_context:LibraryContextImpl',
184-
'lct = openedx.core.djangoapps.content_libraries.library_context:LibraryContextContainerImpl',
185184
],
186185
'openedx.dynamic_partition_generator': [
187186
'content_type_gating = openedx.features.content_type_gating.partitions:create_content_gating_partition',

0 commit comments

Comments
 (0)