99from django .utils .decorators import method_decorator
1010from drf_yasg .utils import swagger_auto_schema
1111from opaque_keys .edx .locator import LibraryLocatorV2 , LibraryUsageLocatorV2
12+ from openedx_authz import api as authz_api
1213from openedx_learning .api import authoring as authoring_api
1314from rest_framework import status
1415from 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