diff --git a/lib/galaxy/tools/actions/__init__.py b/lib/galaxy/tools/actions/__init__.py index 078df82c48c..baae35322e0 100644 --- a/lib/galaxy/tools/actions/__init__.py +++ b/lib/galaxy/tools/actions/__init__.py @@ -512,11 +512,19 @@ class DefaultToolAction(ToolAction): if not completed_job: # Determine output dataset permission/roles list + default_history_permissions = app.security_agent.history_get_default_permissions(history) if all_permissions: output_permissions = app.security_agent.guess_derived_permissions(all_permissions) + # Ensure history default access restrictions are applied even when + # inputs are less restrictive (e.g. public library datasets). The + # history defaults reflect the user's intent for output privacy. + # See https://github.com/galaxyproject/galaxy/issues/21802 + access_action = app.security_agent.get_action("access") + if access_action in default_history_permissions and access_action not in output_permissions: + output_permissions[access_action] = default_history_permissions[access_action] else: # No valid inputs, we will use history defaults - output_permissions = app.security_agent.history_get_default_permissions(history) + output_permissions = default_history_permissions # Add the dbkey to the incoming parameters incoming["dbkey"] = input_dbkey diff --git a/test/integration/objectstore/test_private_handling_library_imports.py b/test/integration/objectstore/test_private_handling_library_imports.py index 5635d73a6bf..806a12df621 100644 --- a/test/integration/objectstore/test_private_handling_library_imports.py +++ b/test/integration/objectstore/test_private_handling_library_imports.py @@ -95,13 +95,11 @@ class TestToolOutputFromLibraryImportWithPrivateObjectStore(BaseObjectStoreInteg ), f"Library import should retain default store, got {copied_storage['object_store_id']}" # Make the imported dataset public — simulating a dataset from a public - # data library where datasets are accessible to all users. This is the - # crux of the bug: the input's access permissions (public) propagate to - # tool outputs, which then conflict with the private object store. + # data library where datasets are accessible to all users. response = self.dataset_populator.make_dataset_public_raw(history_id, copied_hda["id"]) api_asserts.assert_status_code_is_ok(response) - # Run a tool on the library-imported dataset — this is the scenario from the bug + # Run a tool on the library-imported dataset run_response = self.dataset_populator.run_tool( "cat1", inputs={"input1": {"src": "hda", "id": copied_hda["id"]}}, @@ -110,9 +108,6 @@ class TestToolOutputFromLibraryImportWithPrivateObjectStore(BaseObjectStoreInteg self.dataset_populator.wait_for_history(history_id) job = run_response["jobs"][0] job_details = self.dataset_populator.get_job_details(job["id"], full=True).json() - # This is the core assertion — the job should succeed, not fail with - # "Job attempted to create sharable output datasets in a storage location - # with sharing disabled" assert job_details["state"] == "ok", ( f"Tool run on library-imported dataset failed with state '{job_details['state']}'. " f"Expected outputs to respect history's private store preference regardless of input origin."