From 629ababe42206985eb53dee3cc4857e21715f114 Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Fri, 29 Oct 2021 10:00:51 +0200 Subject: [PATCH] Disable library uploads using master API key and cleanup some of the parameter validation. --- lib/galaxy/webapps/base/controller.py | 2 +- .../webapps/galaxy/api/folder_contents.py | 2 ++ .../webapps/galaxy/api/library_contents.py | 32 +++++++------------ lib/galaxy_test/api/test_libraries.py | 23 ++++++++++--- 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/lib/galaxy/webapps/base/controller.py b/lib/galaxy/webapps/base/controller.py index 697de41db07..43717513b41 100644 --- a/lib/galaxy/webapps/base/controller.py +++ b/lib/galaxy/webapps/base/controller.py @@ -488,7 +488,7 @@ class UsesLibraryMixinItems(SharableItemSecurityMixin): this check. """ if not trans.user: - return False + raise exceptions.ItemAccessibilityException("Anonymous users cannot add to library items") current_user_roles = trans.get_current_user_roles() if trans.user_is_admin: diff --git a/lib/galaxy/webapps/galaxy/api/folder_contents.py b/lib/galaxy/webapps/galaxy/api/folder_contents.py index 0fff9bb3c79..01b4c6bbf5f 100644 --- a/lib/galaxy/webapps/galaxy/api/folder_contents.py +++ b/lib/galaxy/webapps/galaxy/api/folder_contents.py @@ -201,6 +201,8 @@ class FolderContentsAPIView(UsesLibraryMixinItems): InsufficientPermissionsException, ItemAccessibilityException, InternalServerError """ + if trans.user_is_bootstrap_admin: + raise exceptions.RealUserRequiredException("Only real users can create a new library file.") encoded_folder_id_16 = self.__decode_library_content_id(trans, encoded_folder_id) from_hda_id = payload.pop('from_hda_id', None) from_hdca_id = payload.pop('from_hdca_id', None) diff --git a/lib/galaxy/webapps/galaxy/api/library_contents.py b/lib/galaxy/webapps/galaxy/api/library_contents.py index d2c8c4f871d..3ea5b567fe6 100644 --- a/lib/galaxy/webapps/galaxy/api/library_contents.py +++ b/lib/galaxy/webapps/galaxy/api/library_contents.py @@ -214,26 +214,21 @@ class LibraryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, in that case a list of such dictionaries is returned. :rtype: object """ + if trans.user_is_bootstrap_admin: + raise exceptions.RealUserRequiredException("Only real users can create a new library file or folder.") if 'create_type' not in payload: - trans.response.status = 400 - return "Missing required 'create_type' parameter." - else: - create_type = payload.pop('create_type') + raise exceptions.RequestParameterMissingException("Missing required 'create_type' parameter.") + create_type = payload.pop('create_type') if create_type not in ('file', 'folder', 'collection'): - trans.response.status = 400 - return "Invalid value for 'create_type' parameter ( %s ) specified." % create_type - + raise exceptions.RequestParameterInvalidException(f"Invalid value for 'create_type' parameter ( {create_type} ) specified.") + if 'upload_option' in payload and payload['upload_option'] not in ('upload_file', 'upload_directory', 'upload_paths'): + raise exceptions.RequestParameterInvalidException(f"Invalid value for 'create_type' parameter ( {payload['upload_option']} ) specified.") if 'folder_id' not in payload: - trans.response.status = 400 - return "Missing required 'folder_id' parameter." - else: - folder_id = payload.pop('folder_id') - class_name, folder_id = self._decode_library_content_id(folder_id) - try: - # security is checked in the downstream controller - parent = self.get_library_folder(trans, folder_id, check_ownership=False, check_accessible=False) - except Exception as e: - return util.unicodify(e) + raise exceptions.RequestParameterMissingException("Missing required 'folder_id' parameter.") + folder_id = payload.pop('folder_id') + _, folder_id = self._decode_library_content_id(folder_id) + # security is checked in the downstream controller + parent = self.get_library_folder(trans, folder_id, check_ownership=False, check_accessible=False) # The rest of the security happens in the library_common controller. real_folder_id = trans.security.encode_id(parent.id) @@ -326,9 +321,6 @@ class LibraryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, error = False if upload_option == 'upload_paths': validate_path_upload(trans) # Duplicate check made in _upload_dataset. - elif upload_option not in ('upload_file', 'upload_directory', 'upload_paths'): - error = True - message = 'Invalid upload_option' elif roles: # Check to see if the user selected roles to associate with the DATASET_ACCESS permission # on the dataset that would cause accessibility issues. diff --git a/lib/galaxy_test/api/test_libraries.py b/lib/galaxy_test/api/test_libraries.py index 796fefe8ec5..37242841c43 100644 --- a/lib/galaxy_test/api/test_libraries.py +++ b/lib/galaxy_test/api/test_libraries.py @@ -78,17 +78,32 @@ class LibrariesApiTestCase(ApiTestCase): create_response = self._create_folder(library) self._assert_status_code_is(create_response, 200) + def test_create_library_dataset_bootstrap_user(self, library_name="private_dataset", wait=True): + library = self.library_populator.new_private_library(library_name) + payload, files = self.library_populator.create_dataset_request(library, file_type="txt", contents="create_test") + create_response = self.galaxy_interactor.post("libraries/%s/contents" % library["id"], payload, files=files, key=self.master_api_key) + self._assert_status_code_is(create_response, 400) + def test_create_dataset_denied(self): + url, payload = self._create_dataset_kwargs() + with self._different_user(): + create_response = self._post(url, payload) + self._assert_status_code_is(create_response, 403) + + def test_create_dataset_bootstrap_admin_user(self): + url, payload = self._create_dataset_kwargs() + with self._different_user(): + create_response = self._post(url, payload, key=self.master_api_key) + self._assert_status_code_is(create_response, 400) + + def _create_dataset_kwargs(self): library = self.library_populator.new_private_library("ForCreateDatasets") folder_response = self._create_folder(library) self._assert_status_code_is(folder_response, 200) folder_id = folder_response.json()[0]['id'] history_id = self.dataset_populator.new_history() hda_id = self.dataset_populator.new_dataset(history_id, content="1 2 3")['id'] - with self._different_user(): - payload = {'from_hda_id': hda_id} - create_response = self._post("folders/%s/contents" % folder_id, payload) - self._assert_status_code_is(create_response, 403) + return f"folders/{folder_id}/contents", {"from_hda_id": hda_id} def test_show_private_dataset_permissions(self): library, library_dataset = self.library_populator.new_library_dataset_in_private_library("ForCreateDatasets", wait=True)