Skip to content

Commit 493be31

Browse files
Merge pull request #21087 from mvdbeek/validate_request
[25.0] Run landing request state through validator
2 parents 1e98bac + e7f96d4 commit 493be31

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

lib/galaxy/managers/landing.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
)
55
from uuid import uuid4
66

7-
from pydantic import UUID4
7+
from pydantic import (
8+
UUID4,
9+
ValidationError,
10+
)
811
from sqlalchemy import select
912

1013
from galaxy.exceptions import (
@@ -30,6 +33,7 @@
3033
)
3134
from galaxy.security.idencoding import IdEncodingHelper
3235
from galaxy.structured_app import StructuredApp
36+
from galaxy.tool_util_models.parameters import DataOrCollectionRequestAdapter
3337
from galaxy.util import safe_str_cmp
3438
from .context import ProvidesUserContext
3539

@@ -73,11 +77,25 @@ def create_workflow_landing_request(self, payload: CreateWorkflowLandingRequestP
7377
model.workflow_source = payload.workflow_id
7478
model.uuid = uuid4()
7579
model.client_secret = payload.client_secret
76-
model.request_state = payload.request_state
80+
model.request_state = self.validate_workflow_request_state(payload.request_state)
7781
model.public = payload.public
7882
self._save(model)
7983
return self._workflow_response(model)
8084

85+
def validate_workflow_request_state(self, request_state: Optional[dict]) -> Optional[dict]:
86+
# This would ideally be run in the context of a workflow input definition
87+
if isinstance(request_state, dict):
88+
for key, value in request_state.items():
89+
if isinstance(value, dict):
90+
try:
91+
# persist values after model validators and aliases have been applied
92+
request_state[key] = DataOrCollectionRequestAdapter.validate_python(value).model_dump(
93+
by_alias=True, exclude_unset=True, mode="json"
94+
)
95+
except ValidationError:
96+
pass
97+
return request_state
98+
8199
def claim_tool_landing_request(
82100
self, trans: ProvidesUserContext, uuid: UUID4, claim: Optional[ClaimLandingPayload]
83101
) -> ToolLandingRequest:

lib/galaxy_test/api/test_landing.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ def test_create_private_workflow_landing_anonymous_user(self):
106106
_cannot_claim_request(self.dataset_populator, response)
107107
_cannot_use_request(self.dataset_populator, response)
108108

109+
@skip_without_tool("cat1")
110+
def test_workflow_landing_uniform_response(self):
111+
request = _get_simple_landing_payload(self.workflow_populator, public=True)
112+
response = self.dataset_populator.create_workflow_landing(request)
113+
landing_request = self.dataset_populator.use_workflow_landing_raw(response.uuid)
114+
# Make sure url is turned into location
115+
assert landing_request["request_state"]["WorkflowInput1"]["location"]
116+
109117
def test_landing_claim_preserves_source_metadata(self):
110118
request = CreateWorkflowLandingRequestPayload(
111119
workflow_id="https://dockstore.org/api/ga4gh/trs/v2/tools/#workflow/github.com/iwc-workflows/chipseq-pe/main/versions/v0.12",

lib/galaxy_test/base/populators.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,12 @@ def use_workflow_landing(self, uuid: UUID4) -> WorkflowLandingRequest:
883883
api_asserts.assert_status_code_is(landing_reponse, 200)
884884
return WorkflowLandingRequest.model_validate(landing_reponse.json())
885885

886+
def use_workflow_landing_raw(self, uuid: UUID4):
887+
url = f"workflow_landings/{uuid}"
888+
landing_reponse = self._get(url, {"client_secret": "foobar"})
889+
api_asserts.assert_status_code_is(landing_reponse, 200)
890+
return landing_reponse.json()
891+
886892
def create_tool_from_path(self, tool_path: str) -> Dict[str, Any]:
887893
tool_directory = os.path.dirname(os.path.abspath(tool_path))
888894
payload = dict(

0 commit comments

Comments
 (0)