Skip to content

Commit a954ce7

Browse files
authored
Add isAllowed field to GraphQL workflow query (#978)
1 parent ac24055 commit a954ce7

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

orchestrator/graphql/schemas/workflow.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from orchestrator.config.assignee import Assignee
66
from orchestrator.db import WorkflowTable
77
from orchestrator.graphql.schemas.helpers import get_original_model
8+
from orchestrator.graphql.types import OrchestratorInfo
89
from orchestrator.schemas import StepSchema, WorkflowSchema
910
from orchestrator.workflows import get_workflow
1011

@@ -30,3 +31,11 @@ async def products(self) -> list[Annotated["ProductType", strawberry.lazy(".prod
3031
@strawberry.field(description="Return all steps for this workflow") # type: ignore
3132
def steps(self) -> list[Step]:
3233
return [Step(name=step.name, assignee=step.assignee) for step in get_workflow(self.name).steps] # type: ignore
34+
35+
@strawberry.field(description="Return whether the currently logged-in used is allowed to start this workflow") # type: ignore
36+
def is_allowed(self, info: OrchestratorInfo) -> bool:
37+
oidc_user = info.context.get_current_user
38+
workflow_table = get_original_model(self, WorkflowTable)
39+
workflow = get_workflow(workflow_table.name)
40+
41+
return workflow.authorize_callback(oidc_user) # type: ignore

test/unit_tests/graphql/test_workflows.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44

55
import pytest
66

7-
from orchestrator import app_settings
7+
from oauth2_lib.fastapi import OIDCUserModel
8+
from orchestrator import app_settings, workflow
9+
from orchestrator.targets import Target
10+
from orchestrator.workflow import done, init
811
from test.unit_tests.fixtures.workflows import add_soft_deleted_workflows # noqa: F401
12+
from test.unit_tests.workflows import WorkflowInstanceForTests
913

1014

1115
@pytest.fixture(autouse=True)
@@ -32,6 +36,7 @@ def get_workflows_query(
3236
workflowId
3337
name
3438
description
39+
isAllowed
3540
createdAt
3641
steps {
3742
name
@@ -81,6 +86,7 @@ def test_workflows_query(test_client):
8186
assert "errors" not in result
8287
assert len(workflows) == 2
8388

89+
assert all(workflow["isAllowed"] for workflow in workflows)
8490
assert all(len(workflow["steps"]) > 0 for workflow in workflows)
8591

8692
assert pageinfo == {
@@ -232,3 +238,23 @@ def test_workflows_sort_by_resource_type_desc(test_client):
232238
"modify_note",
233239
]
234240
assert [rt["name"] for rt in workflows] == expected_workflows
241+
242+
243+
def test_workflows_not_allowed(test_client):
244+
forbidden_workflow_name = "unauthorized_workflow"
245+
246+
def disallow(_: OIDCUserModel | None = None) -> bool:
247+
return False
248+
249+
@workflow(forbidden_workflow_name, target=Target.CREATE, authorize_callback=disallow)
250+
def unauthorized_workflow():
251+
return init >> done
252+
253+
with WorkflowInstanceForTests(unauthorized_workflow, forbidden_workflow_name):
254+
data = get_workflows_query(filter_by=[{"field": "name", "value": forbidden_workflow_name}])
255+
response = test_client.post("/api/graphql", content=data, headers={"Content-Type": "application/json"})
256+
assert HTTPStatus.OK == response.status_code
257+
result = response.json()
258+
259+
workflow_data = result["data"]["workflows"]["page"][0]
260+
assert not workflow_data["isAllowed"]

0 commit comments

Comments
 (0)