Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions lib/galaxy/managers/landing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
)
from uuid import uuid4

from pydantic import UUID4
from pydantic import (
UUID4,
ValidationError,
)
from sqlalchemy import select

from galaxy.exceptions import (
Expand All @@ -30,6 +33,7 @@
)
from galaxy.security.idencoding import IdEncodingHelper
from galaxy.structured_app import StructuredApp
from galaxy.tool_util_models.parameters import DataOrCollectionRequestAdapter
from galaxy.util import safe_str_cmp
from .context import ProvidesUserContext

Expand Down Expand Up @@ -73,11 +77,25 @@ def create_workflow_landing_request(self, payload: CreateWorkflowLandingRequestP
model.workflow_source = payload.workflow_id
model.uuid = uuid4()
model.client_secret = payload.client_secret
model.request_state = payload.request_state
model.request_state = self.validate_workflow_request_state(payload.request_state)
model.public = payload.public
self._save(model)
return self._workflow_response(model)

def validate_workflow_request_state(self, request_state: Optional[dict]) -> Optional[dict]:
# This would ideally be run in the context of a workflow input definition
if isinstance(request_state, dict):
for key, value in request_state.items():
if isinstance(value, dict):
try:
# persist values after model validators and aliases have been applied
request_state[key] = DataOrCollectionRequestAdapter.validate_python(value).model_dump(
by_alias=True, exclude_unset=True, mode="json"
)
except ValidationError:
pass
return request_state

def claim_tool_landing_request(
self, trans: ProvidesUserContext, uuid: UUID4, claim: Optional[ClaimLandingPayload]
) -> ToolLandingRequest:
Expand Down
8 changes: 8 additions & 0 deletions lib/galaxy_test/api/test_landing.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ def test_create_private_workflow_landing_anonymous_user(self):
_cannot_claim_request(self.dataset_populator, response)
_cannot_use_request(self.dataset_populator, response)

@skip_without_tool("cat1")
def test_workflow_landing_uniform_response(self):
request = _get_simple_landing_payload(self.workflow_populator, public=True)
response = self.dataset_populator.create_workflow_landing(request)
landing_request = self.dataset_populator.use_workflow_landing_raw(response.uuid)
# Make sure url is turned into location
assert landing_request["request_state"]["WorkflowInput1"]["location"]

def test_landing_claim_preserves_source_metadata(self):
request = CreateWorkflowLandingRequestPayload(
workflow_id="https://dockstore.org/api/ga4gh/trs/v2/tools/#workflow/github.com/iwc-workflows/chipseq-pe/main/versions/v0.12",
Expand Down
6 changes: 6 additions & 0 deletions lib/galaxy_test/base/populators.py
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,12 @@ def use_workflow_landing(self, uuid: UUID4) -> WorkflowLandingRequest:
api_asserts.assert_status_code_is(landing_reponse, 200)
return WorkflowLandingRequest.model_validate(landing_reponse.json())

def use_workflow_landing_raw(self, uuid: UUID4):
url = f"workflow_landings/{uuid}"
landing_reponse = self._get(url, {"client_secret": "foobar"})
api_asserts.assert_status_code_is(landing_reponse, 200)
return landing_reponse.json()

def create_tool_from_path(self, tool_path: str) -> Dict[str, Any]:
tool_directory = os.path.dirname(os.path.abspath(tool_path))
payload = dict(
Expand Down
Loading