def post(self, request, lib_key_str): """ Add a user to this content library via email, with permissions specified in the request body. """ key = LibraryLocatorV2.from_string(lib_key_str) api.require_permission_for_library_key( key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY_TEAM) serializer = ContentLibraryAddPermissionByEmailSerializer( data=request.data) serializer.is_valid(raise_exception=True) try: user = User.objects.get( email=serializer.validated_data.get('email')) except User.DoesNotExist: raise ValidationError({ 'email': _('We could not find a user with that email address.') }) grant = api.get_library_user_permissions(key, user) if grant: return Response( { 'email': [_('This user already has access to this library.')] }, status=status.HTTP_400_BAD_REQUEST, ) try: api.set_library_user_permissions( key, user, access_level=serializer.validated_data["access_level"]) except api.LibraryPermissionIntegrityError as err: raise ValidationError(detail=str(err)) grant = api.get_library_user_permissions(key, user) return Response(ContentLibraryPermissionSerializer(grant).data)
def get(self, request, lib_key_str): """ Get the list of all top-level blocks in this content library """ key = LibraryLocatorV2.from_string(lib_key_str) text_search = request.query_params.get('text_search', None) block_types = request.query_params.getlist('block_type') or None api.require_permission_for_library_key( key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY) result = api.get_library_blocks(key, text_search=text_search, block_types=block_types) # Verify `pagination` param to maintain compatibility with older # non pagination-aware clients if request.GET.get('pagination', 'false').lower() == 'true': paginator = LibraryApiPagination() result = paginator.paginate_queryset(result, request) serializer = LibraryXBlockMetadataSerializer(result, many=True) return paginator.get_paginated_response(serializer.data) return Response( LibraryXBlockMetadataSerializer(result, many=True).data)
def test_update_libraries(self): """ Test if indexes are updated when libraries are updated """ lib = self._create_library(slug="test-lib-update", title="Title", description="Description") library_key = LibraryLocatorV2.from_string(lib['id']) self._update_library(lib['id'], title="New Title", description="New Title") response = ContentLibraryIndexer.get_libraries([library_key])[0] self.assertEqual(response['id'], lib['id']) self.assertEqual(response['title'], "New Title") self.assertEqual(response['description'], "New Title") self.assertEqual(response['uuid'], lib['bundle_uuid']) self.assertEqual(response['num_blocks'], 0) self.assertEqual(response['version'], lib['version']) self.assertEqual(response['last_published'], None) self.assertEqual(response['has_unpublished_changes'], False) self.assertEqual(response['has_unpublished_deletes'], False) self._delete_library(lib['id']) with self.assertRaises(LibraryNotIndexedException): ContentLibraryIndexer.get_libraries([library_key])
def post(self, request, lib_key_str): """ Add a new XBlock to this content library """ library_key = LibraryLocatorV2.from_string(lib_key_str) api.require_permission_for_library_key(library_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY) serializer = LibraryXBlockCreationSerializer(data=request.data) serializer.is_valid(raise_exception=True) parent_block_usage_str = serializer.validated_data.pop("parent_block", None) if parent_block_usage_str: # Add this as a child of an existing block: parent_block_usage = LibraryUsageLocatorV2.from_string(parent_block_usage_str) if parent_block_usage.context_key != library_key: raise ValidationError(detail={"parent_block": "Usage ID doesn't match library ID in the URL."}) result = api.create_library_block_child(parent_block_usage, **serializer.validated_data) else: # Create a new regular top-level block: try: result = api.create_library_block(library_key, **serializer.validated_data) except api.IncompatibleTypesError as err: raise ValidationError( detail={'block_type': str(err)}, ) return Response(LibraryXBlockMetadataSerializer(result).data)
def test_index_libraries(self): """ Test if libraries are being indexed correctly """ result1 = self._create_library(slug="test-lib-index-1", title="Title 1", description="Description") result2 = self._create_library(slug="test-lib-index-2", title="Title 2", description="Description") for result in [result1, result2]: library_key = LibraryLocatorV2.from_string(result['id']) response = ContentLibraryIndexer.get_items([library_key])[0] assert response['id'] == result['id'] assert response['title'] == result['title'] assert response['description'] == result['description'] assert response['uuid'] == result['bundle_uuid'] assert response['num_blocks'] == 0 assert response['version'] == result['version'] assert response['last_published'] is None assert response['has_unpublished_changes'] is False assert response['has_unpublished_deletes'] is False
def test_update_library_blocks(self): """ Test if indexes are updated when blocks in libraries are updated """ def commit_library_and_verify(library_key): """ Commit library changes, and verify that there are no uncommited changes anymore """ last_published = ContentLibraryIndexer.get_libraries([library_key])[0]['last_published'] self._commit_library_changes(str(library_key)) response = ContentLibraryIndexer.get_libraries([library_key])[0] self.assertEqual(response['has_unpublished_changes'], False) self.assertEqual(response['has_unpublished_deletes'], False) self.assertGreaterEqual(response['last_published'], last_published) return response def verify_uncommitted_libraries(library_key, has_unpublished_changes, has_unpublished_deletes): """ Verify uncommitted changes and deletes in the index """ response = ContentLibraryIndexer.get_libraries([library_key])[0] self.assertEqual(response['has_unpublished_changes'], has_unpublished_changes) self.assertEqual(response['has_unpublished_deletes'], has_unpublished_deletes) return response lib = self._create_library(slug="test-lib-update-block", title="Title", description="Description") library_key = LibraryLocatorV2.from_string(lib['id']) # Verify uncommitted new blocks block = self._add_block_to_library(lib['id'], "problem", "problem1") response = verify_uncommitted_libraries(library_key, True, False) self.assertEqual(response['last_published'], None) self.assertEqual(response['num_blocks'], 1) # Verify committed new blocks self._commit_library_changes(lib['id']) response = verify_uncommitted_libraries(library_key, False, False) self.assertEqual(response['num_blocks'], 1) # Verify uncommitted deleted blocks self._delete_library_block(block['id']) response = verify_uncommitted_libraries(library_key, True, True) self.assertEqual(response['num_blocks'], 0) # Verify committed deleted blocks self._commit_library_changes(lib['id']) response = verify_uncommitted_libraries(library_key, False, False) self.assertEqual(response['num_blocks'], 0) block = self._add_block_to_library(lib['id'], "problem", "problem1") self._commit_library_changes(lib['id']) # Verify changes to blocks # Verify OLX updates on blocks self._set_library_block_olx(block["id"], "<problem/>") verify_uncommitted_libraries(library_key, True, False) commit_library_and_verify(library_key) # Verify asset updates on blocks self._set_library_block_asset(block["id"], "whatever.png", b"data") verify_uncommitted_libraries(library_key, True, False) commit_library_and_verify(library_key) self._delete_library_block_asset(block["id"], "whatever.png", expect_response=204) verify_uncommitted_libraries(library_key, True, False) commit_library_and_verify(library_key) lib2 = self._create_library(slug="test-lib-update-block-2", title="Title 2", description="Description") self._add_block_to_library(lib2["id"], "problem", "problem1") self._commit_library_changes(lib2["id"]) #Verify new links on libraries self._link_to_library(lib["id"], "library_2", lib2["id"]) verify_uncommitted_libraries(library_key, True, False) #Verify reverting uncommitted changes self._revert_library_changes(lib["id"]) verify_uncommitted_libraries(library_key, False, False)