Skip to content

Commit 0e501cd

Browse files
committed
feat: add the new enforcement points in the rest_api/blocks
1 parent aa9ebd0 commit 0e501cd

1 file changed

Lines changed: 64 additions & 30 deletions

File tree

  • openedx/core/djangoapps/content_libraries/rest_api

openedx/core/djangoapps/content_libraries/rest_api/blocks.py

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from django.utils.decorators import method_decorator
1010
from drf_yasg.utils import swagger_auto_schema
1111
from opaque_keys.edx.locator import LibraryLocatorV2, LibraryUsageLocatorV2
12+
from openedx_authz import api as authz_api
1213
from openedx_learning.api import authoring as authoring_api
1314
from rest_framework import status
1415
from rest_framework.exceptions import NotFound, ValidationError
@@ -60,7 +61,9 @@ def get(self, request, lib_key_str):
6061
text_search = request.query_params.get('text_search', None)
6162
block_types = request.query_params.getlist('block_type') or None
6263

63-
api.require_permission_for_library_key(key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
64+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'view_library', str(lib_key_str))
65+
if not is_allowed_with_authz:
66+
api.require_permission_for_library_key(key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
6467
components = api.get_library_components(key, text_search=text_search, block_types=block_types)
6568

6669
paginated_xblock_metadata = [
@@ -80,7 +83,9 @@ def post(self, request, lib_key_str):
8083
Add a new XBlock to this content library
8184
"""
8285
library_key = LibraryLocatorV2.from_string(lib_key_str)
83-
api.require_permission_for_library_key(library_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY)
86+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'edit_library_content', str(lib_key_str))
87+
if not is_allowed_with_authz:
88+
api.require_permission_for_library_key(library_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY)
8489
serializer = serializers.LibraryXBlockCreationSerializer(data=request.data)
8590
serializer.is_valid(raise_exception=True)
8691

@@ -115,7 +120,9 @@ def get(self, request, usage_key_str):
115120
versioning.
116121
"""
117122
key = LibraryUsageLocatorV2.from_string(usage_key_str)
118-
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
123+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'view_library', str(usage_key_str))
124+
if not is_allowed_with_authz:
125+
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
119126
result = api.get_library_block(key, include_collections=True)
120127

121128
return Response(self.serializer_class(result).data)
@@ -134,7 +141,9 @@ def delete(self, request, usage_key_str): # pylint: disable=unused-argument
134141
be deleted but the link and the linked bundle will be unaffected.
135142
"""
136143
key = LibraryUsageLocatorV2.from_string(usage_key_str)
137-
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY)
144+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'edit_library_content', str(usage_key_str))
145+
if not is_allowed_with_authz:
146+
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY)
138147
api.delete_library_block(key, user_id=request.user.id)
139148
return Response({})
140149

@@ -153,7 +162,9 @@ def get(self, request, usage_key_str):
153162
List the static asset files belonging to this block.
154163
"""
155164
key = LibraryUsageLocatorV2.from_string(usage_key_str)
156-
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
165+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'view_library', str(usage_key_str))
166+
if not is_allowed_with_authz:
167+
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
157168
files = api.get_library_block_static_asset_files(key)
158169
return Response(self.serializer_class({"files": files}).data)
159170

@@ -173,7 +184,9 @@ def get(self, request, usage_key_str, file_path):
173184
Get a static asset file belonging to this block.
174185
"""
175186
key = LibraryUsageLocatorV2.from_string(usage_key_str)
176-
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
187+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'view_library', str(usage_key_str))
188+
if not is_allowed_with_authz:
189+
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
177190
files = api.get_library_block_static_asset_files(key)
178191
for f in files:
179192
if f.path == file_path:
@@ -187,9 +200,11 @@ def put(self, request, usage_key_str, file_path):
187200
"""
188201
file_path = file_path.replace(" ", "_") # Messes up url/name correspondence due to URL encoding.
189202
usage_key = LibraryUsageLocatorV2.from_string(usage_key_str)
190-
api.require_permission_for_library_key(
191-
usage_key.lib_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY,
192-
)
203+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'edit_library_content', str(usage_key_str))
204+
if not is_allowed_with_authz:
205+
api.require_permission_for_library_key(
206+
usage_key.lib_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY,
207+
)
193208
file_wrapper = request.data['content']
194209
if file_wrapper.size > 20 * 1024 * 1024: # > 20 MiB
195210
# TODO: This check was written when V2 Libraries were backed by the Blockstore micro-service.
@@ -212,9 +227,11 @@ def delete(self, request, usage_key_str, file_path):
212227
Delete a static asset file belonging to this block.
213228
"""
214229
usage_key = LibraryUsageLocatorV2.from_string(usage_key_str)
215-
api.require_permission_for_library_key(
216-
usage_key.lib_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY,
217-
)
230+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'edit_library_content', str(usage_key_str))
231+
if not is_allowed_with_authz:
232+
api.require_permission_for_library_key(
233+
usage_key.lib_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY,
234+
)
218235
try:
219236
api.delete_library_block_static_asset_file(usage_key, file_path, request.user)
220237
except ValueError:
@@ -235,11 +252,13 @@ def post(self, request, usage_key_str):
235252
Publish the draft changes made to this component.
236253
"""
237254
key = LibraryUsageLocatorV2.from_string(usage_key_str)
238-
api.require_permission_for_library_key(
239-
key.lib_key,
240-
request.user,
241-
permissions.CAN_EDIT_THIS_CONTENT_LIBRARY
242-
)
255+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'publish_library_content', str(usage_key_str))
256+
if not is_allowed_with_authz:
257+
api.require_permission_for_library_key(
258+
key.lib_key,
259+
request.user,
260+
permissions.CAN_EDIT_THIS_CONTENT_LIBRARY
261+
)
243262
api.publish_component_changes(key, request.user)
244263
return Response({})
245264

@@ -258,11 +277,14 @@ def patch(self, request: RestRequest, usage_key_str) -> Response:
258277
Collection and Components must all be part of the given library/learning package.
259278
"""
260279
key = LibraryUsageLocatorV2.from_string(usage_key_str)
261-
content_library = api.require_permission_for_library_key(
262-
key.lib_key,
263-
request.user,
264-
permissions.CAN_EDIT_THIS_CONTENT_LIBRARY
265-
)
280+
content_library = api.get_library(usage_key_str)
281+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'edit_library_content', str(usage_key_str))
282+
if not is_allowed_with_authz:
283+
api.require_permission_for_library_key(
284+
key.lib_key,
285+
request.user,
286+
permissions.CAN_EDIT_THIS_CONTENT_LIBRARY
287+
)
266288
serializer = serializers.ContentLibraryItemCollectionsUpdateSerializer(data=request.data)
267289
serializer.is_valid(raise_exception=True)
268290

@@ -293,7 +315,9 @@ def get(self, request, usage_key_str):
293315
Get the LTI launch URL for the XBlock.
294316
"""
295317
key = LibraryUsageLocatorV2.from_string(usage_key_str)
296-
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
318+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'view_library', str(usage_key_str))
319+
if not is_allowed_with_authz:
320+
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
297321

298322
# Get the block to validate its existence
299323
api.get_library_block(key)
@@ -318,7 +342,9 @@ def get(self, request, usage_key_str):
318342
Get the block's OLX
319343
"""
320344
key = LibraryUsageLocatorV2.from_string(usage_key_str)
321-
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
345+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'view_library', str(usage_key_str))
346+
if not is_allowed_with_authz:
347+
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
322348
xml_str = xblock_api.get_block_draft_olx(key)
323349
return Response(self.serializer_class({"olx": xml_str}).data)
324350

@@ -331,7 +357,9 @@ def post(self, request, usage_key_str):
331357
Very little validation is done.
332358
"""
333359
key = LibraryUsageLocatorV2.from_string(usage_key_str)
334-
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY)
360+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'edit_library_content', str(usage_key_str))
361+
if not is_allowed_with_authz:
362+
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY)
335363
serializer = self.serializer_class(data=request.data)
336364
serializer.is_valid(raise_exception=True)
337365
new_olx_str = serializer.validated_data["olx"]
@@ -353,7 +381,9 @@ def post(self, request, usage_key_str) -> Response:
353381
Restores a soft-deleted library block that belongs to a Content Library
354382
"""
355383
key = LibraryUsageLocatorV2.from_string(usage_key_str)
356-
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY)
384+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'edit_library_content', str(usage_key_str))
385+
if not is_allowed_with_authz:
386+
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY)
357387
api.restore_library_block(key, request.user.id)
358388
return Response(None, status=status.HTTP_204_NO_CONTENT)
359389

@@ -372,7 +402,9 @@ def get(self, request, usage_key_str) -> Response:
372402
Fetches and returns the full container hierarchy for the given library block.
373403
"""
374404
key = LibraryUsageLocatorV2.from_string(usage_key_str)
375-
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
405+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'view_library', str(usage_key_str))
406+
if not is_allowed_with_authz:
407+
api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY)
376408
hierarchy = api.get_library_object_hierarchy(key)
377409
return Response(self.serializer_class(hierarchy).data)
378410

@@ -400,9 +432,11 @@ def get_component_version_asset(request, component_version_uuid, asset_path):
400432
# Permissions check...
401433
learning_package = component_version.component.learning_package
402434
library_key = LibraryLocatorV2.from_string(learning_package.key)
403-
api.require_permission_for_library_key(
404-
library_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY,
405-
)
435+
is_allowed_with_authz = authz_api.is_user_allowed(request.user.username, 'view_library', str(library_key))
436+
if not is_allowed_with_authz:
437+
api.require_permission_for_library_key(
438+
library_key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY,
439+
)
406440

407441
# We already have logic for getting the correct content and generating the
408442
# proper headers in Learning Core, but the response generated here is an

0 commit comments

Comments
 (0)