planar 0.10.0__py3-none-any.whl → 0.11.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- planar/app.py +18 -6
- planar/routers/info.py +79 -36
- planar/scaffold_templates/pyproject.toml.j2 +1 -1
- planar/testing/fixtures.py +7 -4
- {planar-0.10.0.dist-info → planar-0.11.0.dist-info}/METADATA +9 -1
- {planar-0.10.0.dist-info → planar-0.11.0.dist-info}/RECORD +8 -60
- planar/ai/test_agent_serialization.py +0 -229
- planar/ai/test_agent_tool_step_display.py +0 -78
- planar/data/test_dataset.py +0 -358
- planar/files/storage/test_azure_blob.py +0 -435
- planar/files/storage/test_local_directory.py +0 -162
- planar/files/storage/test_s3.py +0 -299
- planar/files/test_files.py +0 -282
- planar/human/test_human.py +0 -385
- planar/logging/test_formatter.py +0 -327
- planar/modeling/mixins/test_auditable.py +0 -97
- planar/modeling/mixins/test_timestamp.py +0 -134
- planar/modeling/mixins/test_uuid_primary_key.py +0 -52
- planar/routers/test_agents_router.py +0 -174
- planar/routers/test_dataset_router.py +0 -429
- planar/routers/test_files_router.py +0 -49
- planar/routers/test_object_config_router.py +0 -367
- planar/routers/test_routes_security.py +0 -168
- planar/routers/test_rule_router.py +0 -470
- planar/routers/test_workflow_router.py +0 -564
- planar/rules/test_data/account_dormancy_management.json +0 -223
- planar/rules/test_data/airline_loyalty_points_calculator.json +0 -262
- planar/rules/test_data/applicant_risk_assessment.json +0 -435
- planar/rules/test_data/booking_fraud_detection.json +0 -407
- planar/rules/test_data/cellular_data_rollover_system.json +0 -258
- planar/rules/test_data/clinical_trial_eligibility_screener.json +0 -437
- planar/rules/test_data/customer_lifetime_value.json +0 -143
- planar/rules/test_data/import_duties_calculator.json +0 -289
- planar/rules/test_data/insurance_prior_authorization.json +0 -443
- planar/rules/test_data/online_check_in_eligibility_system.json +0 -254
- planar/rules/test_data/order_consolidation_system.json +0 -375
- planar/rules/test_data/portfolio_risk_monitor.json +0 -471
- planar/rules/test_data/supply_chain_risk.json +0 -253
- planar/rules/test_data/warehouse_cross_docking.json +0 -237
- planar/rules/test_rules.py +0 -1494
- planar/security/tests/test_auth_middleware.py +0 -162
- planar/security/tests/test_authorization_context.py +0 -78
- planar/security/tests/test_cedar_basics.py +0 -41
- planar/security/tests/test_cedar_policies.py +0 -158
- planar/security/tests/test_jwt_principal_context.py +0 -179
- planar/test_app.py +0 -142
- planar/test_cli.py +0 -394
- planar/test_config.py +0 -515
- planar/test_object_config.py +0 -527
- planar/test_object_registry.py +0 -14
- planar/test_sqlalchemy.py +0 -193
- planar/test_utils.py +0 -105
- planar/testing/test_memory_storage.py +0 -143
- planar/workflows/test_concurrency_detection.py +0 -120
- planar/workflows/test_lock_timeout.py +0 -140
- planar/workflows/test_serialization.py +0 -1203
- planar/workflows/test_suspend_deserialization.py +0 -231
- planar/workflows/test_workflow.py +0 -2005
- {planar-0.10.0.dist-info → planar-0.11.0.dist-info}/WHEEL +0 -0
- {planar-0.10.0.dist-info → planar-0.11.0.dist-info}/entry_points.txt +0 -0
@@ -1,367 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Tests for object configuration router endpoints.
|
3
|
-
|
4
|
-
This module tests the object configuration router endpoints to ensure they work correctly
|
5
|
-
for both agent and rule configurations.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from typing import AsyncGenerator
|
9
|
-
from uuid import UUID, uuid4
|
10
|
-
|
11
|
-
import pytest
|
12
|
-
from pydantic import BaseModel, Field
|
13
|
-
from sqlmodel.ext.asyncio.session import AsyncSession
|
14
|
-
|
15
|
-
from planar.ai.agent import Agent
|
16
|
-
from planar.ai.agent_utils import agent_configuration
|
17
|
-
from planar.ai.models import AgentConfig
|
18
|
-
from planar.app import PlanarApp
|
19
|
-
from planar.config import sqlite_config
|
20
|
-
from planar.object_config import DEFAULT_UUID, ObjectConfiguration
|
21
|
-
from planar.object_config.object_config import ConfigurableObjectType
|
22
|
-
from planar.object_registry import ObjectRegistry
|
23
|
-
from planar.rules.decorator import rule
|
24
|
-
from planar.rules.models import Rule, RuleEngineConfig, create_jdm_graph
|
25
|
-
from planar.rules.rule_configuration import rule_configuration
|
26
|
-
from planar.testing.planar_test_client import PlanarTestClient
|
27
|
-
|
28
|
-
|
29
|
-
class InputForTestRule(BaseModel):
|
30
|
-
"""Input for test rule."""
|
31
|
-
|
32
|
-
value: int = Field(description="Test value")
|
33
|
-
category: str = Field(description="Test category")
|
34
|
-
|
35
|
-
|
36
|
-
class OutputFromTestRule(BaseModel):
|
37
|
-
"""Output from test rule."""
|
38
|
-
|
39
|
-
result: int = Field(description="Result value")
|
40
|
-
message: str = Field(description="Result message")
|
41
|
-
|
42
|
-
|
43
|
-
@pytest.fixture(name="app")
|
44
|
-
def app_fixture(tmp_db_path: str):
|
45
|
-
"""Create a test app with agents and rules."""
|
46
|
-
app = PlanarApp(
|
47
|
-
config=sqlite_config(tmp_db_path),
|
48
|
-
title="Test app for object config router",
|
49
|
-
description="Testing object configuration endpoints",
|
50
|
-
)
|
51
|
-
|
52
|
-
# Register a simple agent
|
53
|
-
simple_agent = Agent(
|
54
|
-
name="test_agent",
|
55
|
-
system_prompt="Test system prompt",
|
56
|
-
user_prompt="Test user prompt: {input}",
|
57
|
-
model="openai:gpt-4o",
|
58
|
-
max_turns=2,
|
59
|
-
)
|
60
|
-
app.register_agent(simple_agent)
|
61
|
-
|
62
|
-
# Create and register a rule
|
63
|
-
@rule(description="Test rule for configuration")
|
64
|
-
def test_rule(input: InputForTestRule) -> OutputFromTestRule:
|
65
|
-
# Default implementation
|
66
|
-
return OutputFromTestRule(
|
67
|
-
result=input.value * 2, message=f"Processed {input.category}"
|
68
|
-
)
|
69
|
-
|
70
|
-
app.register_rule(test_rule)
|
71
|
-
|
72
|
-
return app
|
73
|
-
|
74
|
-
|
75
|
-
@pytest.fixture
|
76
|
-
async def agent_with_configs(app: PlanarApp, session: AsyncSession):
|
77
|
-
"""Create an agent with multiple configurations."""
|
78
|
-
# First config
|
79
|
-
agent_config_1 = AgentConfig(
|
80
|
-
system_prompt="Config 1 system",
|
81
|
-
user_prompt="Config 1 user: {input}",
|
82
|
-
model="openai:gpt-4o",
|
83
|
-
max_turns=3,
|
84
|
-
)
|
85
|
-
await agent_configuration.write_config("test_agent", agent_config_1)
|
86
|
-
|
87
|
-
# Second config
|
88
|
-
agent_config_2 = AgentConfig(
|
89
|
-
system_prompt="Config 2 system",
|
90
|
-
user_prompt="Config 2 user: {input}",
|
91
|
-
model="anthropic:claude-3-sonnet",
|
92
|
-
max_turns=5,
|
93
|
-
)
|
94
|
-
config_2 = await agent_configuration.write_config("test_agent", agent_config_2)
|
95
|
-
|
96
|
-
# Make the second config active
|
97
|
-
await agent_configuration.promote_config(config_2.id)
|
98
|
-
|
99
|
-
return config_2.id
|
100
|
-
|
101
|
-
|
102
|
-
@pytest.fixture
|
103
|
-
async def rule_with_configs(
|
104
|
-
session: AsyncSession,
|
105
|
-
) -> AsyncGenerator[tuple[Rule, list[ObjectConfiguration]], None]:
|
106
|
-
class RuleInputOutput(BaseModel):
|
107
|
-
test: str
|
108
|
-
|
109
|
-
rule = Rule(
|
110
|
-
name=f"test_rule_promote_{uuid4().hex}",
|
111
|
-
description="Test rule for promoting configuration",
|
112
|
-
input=RuleInputOutput,
|
113
|
-
output=RuleInputOutput,
|
114
|
-
)
|
115
|
-
ObjectRegistry.get_instance().register(rule)
|
116
|
-
|
117
|
-
# Create some configs
|
118
|
-
jdm_config_1 = create_jdm_graph(rule)
|
119
|
-
jdm_config_2 = create_jdm_graph(rule)
|
120
|
-
|
121
|
-
rule_config_1 = RuleEngineConfig(jdm=jdm_config_1)
|
122
|
-
rule_config_2 = RuleEngineConfig(jdm=jdm_config_2)
|
123
|
-
|
124
|
-
config1 = await rule_configuration.write_config(rule.name, rule_config_1)
|
125
|
-
config2 = await rule_configuration.write_config(rule.name, rule_config_2)
|
126
|
-
|
127
|
-
yield rule, [config1, config2]
|
128
|
-
|
129
|
-
|
130
|
-
async def test_promote_agent_config(
|
131
|
-
client: PlanarTestClient,
|
132
|
-
app: PlanarApp,
|
133
|
-
session: AsyncSession,
|
134
|
-
agent_with_configs: UUID,
|
135
|
-
):
|
136
|
-
"""Test promoting an agent configuration."""
|
137
|
-
# Get the configurations first to find a non-active one
|
138
|
-
agent = app._object_registry.get_agents()[0]
|
139
|
-
configs = await agent_configuration.read_configs_with_default(
|
140
|
-
"test_agent", agent.to_config()
|
141
|
-
)
|
142
|
-
|
143
|
-
# Find the first (inactive) config
|
144
|
-
inactive_config = next(c for c in configs if not c.active)
|
145
|
-
|
146
|
-
# Promote the inactive config
|
147
|
-
request_data = {
|
148
|
-
"object_type": ConfigurableObjectType.AGENT,
|
149
|
-
"config_id": str(inactive_config.id),
|
150
|
-
"object_name": "test_agent",
|
151
|
-
}
|
152
|
-
|
153
|
-
response = await client.post(
|
154
|
-
"/planar/v1/object-configurations/promote", json=request_data
|
155
|
-
)
|
156
|
-
assert response.status_code == 200
|
157
|
-
|
158
|
-
result = response.json()
|
159
|
-
assert "configs" in result
|
160
|
-
assert len(result["configs"]) >= 3 # At least 2 configs + default
|
161
|
-
|
162
|
-
# Verify the promoted config is now active
|
163
|
-
promoted_config = next(
|
164
|
-
c for c in result["configs"] if c["id"] == str(inactive_config.id)
|
165
|
-
)
|
166
|
-
assert promoted_config["active"] is True
|
167
|
-
|
168
|
-
# Verify other configs are inactive
|
169
|
-
for config in result["configs"]:
|
170
|
-
if config["id"] != str(inactive_config.id):
|
171
|
-
assert config["active"] is False
|
172
|
-
|
173
|
-
|
174
|
-
async def test_promote_rule_config(
|
175
|
-
client: PlanarTestClient,
|
176
|
-
app: PlanarApp,
|
177
|
-
session: AsyncSession,
|
178
|
-
):
|
179
|
-
"""Test promoting a rule configuration."""
|
180
|
-
# Get the configurations first to find a non-active one
|
181
|
-
rule = ObjectRegistry.get_instance().get_rules()[0]
|
182
|
-
|
183
|
-
await rule_configuration.write_config(
|
184
|
-
rule.name, RuleEngineConfig(jdm=create_jdm_graph(rule))
|
185
|
-
)
|
186
|
-
|
187
|
-
configs = await rule_configuration.read_configs_with_default(
|
188
|
-
rule.name, rule.to_config()
|
189
|
-
)
|
190
|
-
|
191
|
-
assert len(configs) == 2
|
192
|
-
|
193
|
-
# Find the first (inactive) config
|
194
|
-
inactive_config = next(c for c in configs if not c.active)
|
195
|
-
|
196
|
-
# Promote the inactive config
|
197
|
-
request_data = {
|
198
|
-
"object_type": ConfigurableObjectType.RULE,
|
199
|
-
"config_id": str(inactive_config.id),
|
200
|
-
"object_name": rule.name,
|
201
|
-
}
|
202
|
-
|
203
|
-
response = await client.post(
|
204
|
-
"/planar/v1/object-configurations/promote", json=request_data
|
205
|
-
)
|
206
|
-
assert response.status_code == 200
|
207
|
-
|
208
|
-
result = response.json()
|
209
|
-
assert "configs" in result
|
210
|
-
assert len(result["configs"]) == 2
|
211
|
-
|
212
|
-
# Verify the promoted config is now active
|
213
|
-
promoted_config = next(
|
214
|
-
c for c in result["configs"] if c["id"] == str(inactive_config.id)
|
215
|
-
)
|
216
|
-
assert promoted_config["active"] is True
|
217
|
-
|
218
|
-
# Verify the config data is correct
|
219
|
-
assert promoted_config["object_type"] == "rule"
|
220
|
-
assert promoted_config["object_name"] == rule.name
|
221
|
-
assert "jdm" in promoted_config["data"]
|
222
|
-
|
223
|
-
|
224
|
-
async def test_promote_to_default_agent(
|
225
|
-
client: PlanarTestClient,
|
226
|
-
app: PlanarApp,
|
227
|
-
session: AsyncSession,
|
228
|
-
agent_with_configs: UUID,
|
229
|
-
):
|
230
|
-
"""Test promoting to default (revert to original implementation) for agent."""
|
231
|
-
# Promote to default using the special UUID
|
232
|
-
request_data = {
|
233
|
-
"object_type": ConfigurableObjectType.AGENT,
|
234
|
-
"config_id": str(DEFAULT_UUID),
|
235
|
-
"object_name": "test_agent",
|
236
|
-
}
|
237
|
-
|
238
|
-
response = await client.post(
|
239
|
-
"/planar/v1/object-configurations/promote", json=request_data
|
240
|
-
)
|
241
|
-
assert response.status_code == 200
|
242
|
-
|
243
|
-
result = response.json()
|
244
|
-
assert "configs" in result
|
245
|
-
|
246
|
-
# Verify all non-default configs are inactive
|
247
|
-
for config in result["configs"]:
|
248
|
-
if config["version"] == 0: # Default config
|
249
|
-
assert config["active"] is True
|
250
|
-
else:
|
251
|
-
assert config["active"] is False
|
252
|
-
|
253
|
-
|
254
|
-
async def test_promote_to_default_rule(
|
255
|
-
client: PlanarTestClient,
|
256
|
-
app: PlanarApp,
|
257
|
-
session: AsyncSession,
|
258
|
-
rule_with_configs: UUID,
|
259
|
-
):
|
260
|
-
"""Test promoting to default (revert to original implementation) for rule."""
|
261
|
-
# Promote to default using the special UUID
|
262
|
-
request_data = {
|
263
|
-
"object_type": ConfigurableObjectType.RULE,
|
264
|
-
"config_id": str(DEFAULT_UUID),
|
265
|
-
"object_name": "test_rule",
|
266
|
-
}
|
267
|
-
|
268
|
-
response = await client.post(
|
269
|
-
"/planar/v1/object-configurations/promote", json=request_data
|
270
|
-
)
|
271
|
-
assert response.status_code == 200
|
272
|
-
|
273
|
-
result = response.json()
|
274
|
-
assert "configs" in result
|
275
|
-
|
276
|
-
# Verify all non-default configs are inactive
|
277
|
-
for config in result["configs"]:
|
278
|
-
if config["version"] == 0: # Default config
|
279
|
-
assert config["active"] is True
|
280
|
-
else:
|
281
|
-
assert config["active"] is False
|
282
|
-
|
283
|
-
|
284
|
-
async def test_promote_nonexistent_agent(
|
285
|
-
client: PlanarTestClient, app: PlanarApp, session: AsyncSession
|
286
|
-
):
|
287
|
-
"""Test promoting config for non-existent agent."""
|
288
|
-
request_data = {
|
289
|
-
"object_type": ConfigurableObjectType.AGENT,
|
290
|
-
"config_id": str(UUID("12345678-1234-5678-1234-567812345678")),
|
291
|
-
"object_name": "nonexistent_agent",
|
292
|
-
}
|
293
|
-
|
294
|
-
response = await client.post(
|
295
|
-
"/planar/v1/object-configurations/promote", json=request_data
|
296
|
-
)
|
297
|
-
assert response.status_code == 404
|
298
|
-
assert response.json()["detail"] == "Agent not found"
|
299
|
-
|
300
|
-
|
301
|
-
async def test_promote_nonexistent_rule(
|
302
|
-
client: PlanarTestClient, app: PlanarApp, session: AsyncSession
|
303
|
-
):
|
304
|
-
"""Test promoting config for non-existent rule."""
|
305
|
-
request_data = {
|
306
|
-
"object_type": ConfigurableObjectType.RULE,
|
307
|
-
"config_id": str(UUID("12345678-1234-5678-1234-567812345678")),
|
308
|
-
"object_name": "nonexistent_rule",
|
309
|
-
}
|
310
|
-
|
311
|
-
response = await client.post(
|
312
|
-
"/planar/v1/object-configurations/promote", json=request_data
|
313
|
-
)
|
314
|
-
assert response.status_code == 404
|
315
|
-
assert response.json()["detail"] == "Rule not found"
|
316
|
-
|
317
|
-
|
318
|
-
async def test_promote_nonexistent_config(
|
319
|
-
client: PlanarTestClient,
|
320
|
-
app: PlanarApp,
|
321
|
-
session: AsyncSession,
|
322
|
-
agent_with_configs: UUID,
|
323
|
-
):
|
324
|
-
"""Test promoting a non-existent configuration."""
|
325
|
-
# Try to promote a config that doesn't exist
|
326
|
-
request_data = {
|
327
|
-
"object_type": ConfigurableObjectType.AGENT,
|
328
|
-
"config_id": str(UUID("99999999-9999-9999-9999-999999999999")),
|
329
|
-
"object_name": "test_agent",
|
330
|
-
}
|
331
|
-
|
332
|
-
# This should fail with an error from the promote_config method
|
333
|
-
response = await client.post(
|
334
|
-
"/planar/v1/object-configurations/promote", json=request_data
|
335
|
-
)
|
336
|
-
assert response.status_code == 404
|
337
|
-
|
338
|
-
|
339
|
-
async def test_config_versions_ordering(
|
340
|
-
client: PlanarTestClient,
|
341
|
-
app: PlanarApp,
|
342
|
-
session: AsyncSession,
|
343
|
-
agent_with_configs: UUID,
|
344
|
-
):
|
345
|
-
"""Test that configurations are returned in correct version order."""
|
346
|
-
# Promote to ensure we have a known state
|
347
|
-
request_data = {
|
348
|
-
"object_type": ConfigurableObjectType.AGENT,
|
349
|
-
"config_id": str(agent_with_configs),
|
350
|
-
"object_name": "test_agent",
|
351
|
-
}
|
352
|
-
|
353
|
-
response = await client.post(
|
354
|
-
"/planar/v1/object-configurations/promote", json=request_data
|
355
|
-
)
|
356
|
-
assert response.status_code == 200
|
357
|
-
|
358
|
-
result = response.json()
|
359
|
-
configs = result["configs"]
|
360
|
-
|
361
|
-
# Verify configs are ordered by version descending (except default which is always last)
|
362
|
-
non_default_configs = [c for c in configs if c["version"] != 0]
|
363
|
-
versions = [c["version"] for c in non_default_configs]
|
364
|
-
assert versions == sorted(versions, reverse=True)
|
365
|
-
|
366
|
-
# Verify default config is last
|
367
|
-
assert configs[-1]["version"] == 0
|
@@ -1,168 +0,0 @@
|
|
1
|
-
from http import HTTPStatus
|
2
|
-
|
3
|
-
import pytest
|
4
|
-
|
5
|
-
from planar import PlanarApp, sqlite_config
|
6
|
-
from planar.config import AuthzConfig, SecurityConfig
|
7
|
-
from planar.security.auth_context import Principal, clear_principal, set_principal
|
8
|
-
from planar.testing.planar_test_client import PlanarTestClient
|
9
|
-
from planar.workflows import workflow
|
10
|
-
|
11
|
-
|
12
|
-
# ------ TEST SETUP ------
|
13
|
-
@workflow()
|
14
|
-
async def simple_test_workflow(test_id: str) -> str:
|
15
|
-
"""
|
16
|
-
Simpleorkflow that returns the test id
|
17
|
-
"""
|
18
|
-
return test_id
|
19
|
-
|
20
|
-
|
21
|
-
@pytest.fixture(name="app_with_no_authz")
|
22
|
-
def create_app_no_authz():
|
23
|
-
config = sqlite_config("test_authz_router.db")
|
24
|
-
|
25
|
-
return PlanarApp(
|
26
|
-
config=config,
|
27
|
-
title="Test Authorization in Router",
|
28
|
-
description="API for testing workflow routers",
|
29
|
-
).register_workflow(simple_test_workflow)
|
30
|
-
|
31
|
-
|
32
|
-
@pytest.fixture(name="app_with_default_authz")
|
33
|
-
def create_app_with_authz():
|
34
|
-
config = sqlite_config("test_authz_router.db")
|
35
|
-
config.security = SecurityConfig(authz=AuthzConfig(enabled=True, policy_file=None))
|
36
|
-
|
37
|
-
return PlanarApp(
|
38
|
-
config=config,
|
39
|
-
title="Test Authorization in Router",
|
40
|
-
description="API for testing workflow routers",
|
41
|
-
).register_workflow(simple_test_workflow)
|
42
|
-
|
43
|
-
|
44
|
-
@pytest.fixture
|
45
|
-
def restrictive_policy_file(tmp_path):
|
46
|
-
"""Create a restrictive policy file for testing."""
|
47
|
-
policy_content = """
|
48
|
-
// Only allow Workflow::List actions when role is admin
|
49
|
-
permit (
|
50
|
-
principal,
|
51
|
-
action == Action::"Workflow::List",
|
52
|
-
resource
|
53
|
-
) when {
|
54
|
-
principal.role == "admin"
|
55
|
-
};
|
56
|
-
|
57
|
-
"""
|
58
|
-
policy_file = tmp_path / "restrictive_policies.cedar"
|
59
|
-
policy_file.write_text(policy_content)
|
60
|
-
return str(policy_file)
|
61
|
-
|
62
|
-
|
63
|
-
@pytest.fixture(name="app_with_restricted_authz")
|
64
|
-
def create_app_with_restricted_authz(tmp_path, restrictive_policy_file):
|
65
|
-
db_path = tmp_path / "test_authz_router.db"
|
66
|
-
config = sqlite_config(str(db_path))
|
67
|
-
config.security = SecurityConfig(
|
68
|
-
authz=AuthzConfig(enabled=True, policy_file=restrictive_policy_file)
|
69
|
-
)
|
70
|
-
|
71
|
-
return PlanarApp(
|
72
|
-
config=config,
|
73
|
-
title="Test Authorization in Router",
|
74
|
-
description="API for testing workflow routers",
|
75
|
-
).register_workflow(simple_test_workflow)
|
76
|
-
|
77
|
-
|
78
|
-
# ------ TESTS ------
|
79
|
-
|
80
|
-
|
81
|
-
def assert_workflow_list(response):
|
82
|
-
# Verify the response status code
|
83
|
-
assert response.status_code == 200
|
84
|
-
|
85
|
-
# Parse the response data
|
86
|
-
data = response.json()
|
87
|
-
|
88
|
-
# Verify that two workflows are returned
|
89
|
-
assert data["total"] == 1
|
90
|
-
assert len(data["items"]) == 1
|
91
|
-
|
92
|
-
assert data["offset"] == 0
|
93
|
-
assert data["limit"] == 10
|
94
|
-
|
95
|
-
# Verify the expense workflow details
|
96
|
-
simple_test_workflow = next(
|
97
|
-
item for item in data["items"] if item["name"] == "simple_test_workflow"
|
98
|
-
)
|
99
|
-
assert simple_test_workflow["fully_qualified_name"] == "simple_test_workflow"
|
100
|
-
|
101
|
-
# # Verify that the workflows have input and output schemas
|
102
|
-
assert "input_schema" in simple_test_workflow
|
103
|
-
assert "output_schema" in simple_test_workflow
|
104
|
-
|
105
|
-
|
106
|
-
async def test_list_workflows_no_authz(app_with_no_authz):
|
107
|
-
"""
|
108
|
-
Test that the workflow management router correctly lists registered workflows.
|
109
|
-
"""
|
110
|
-
|
111
|
-
async with app_with_no_authz._lifespan(app_with_no_authz.fastapi):
|
112
|
-
client = PlanarTestClient(app_with_no_authz)
|
113
|
-
# Call the workflow management endpoint to list workflows
|
114
|
-
response = await client.get("/planar/v1/workflows/")
|
115
|
-
assert_workflow_list(response)
|
116
|
-
|
117
|
-
|
118
|
-
async def test_list_workflows_with_default_authz(app_with_default_authz):
|
119
|
-
"""
|
120
|
-
Test that the workflow management router correctly lists registered workflows when authorization is enabled but no policy file is provided.
|
121
|
-
"""
|
122
|
-
|
123
|
-
async with app_with_default_authz._lifespan(app_with_default_authz.fastapi):
|
124
|
-
client = PlanarTestClient(app_with_default_authz)
|
125
|
-
principal = Principal(sub="test_user") # type: ignore
|
126
|
-
token = set_principal(principal)
|
127
|
-
|
128
|
-
# Call the workflow management endpoint to list workflows
|
129
|
-
response = await client.get("/planar/v1/workflows/")
|
130
|
-
assert_workflow_list(response)
|
131
|
-
|
132
|
-
clear_principal(token)
|
133
|
-
|
134
|
-
|
135
|
-
async def test_list_workflows_with_restricted_authz(app_with_restricted_authz):
|
136
|
-
"""
|
137
|
-
Test that the workflow management router correctly lists registered workflows when authorization is enabled and a policy file is provided.
|
138
|
-
"""
|
139
|
-
|
140
|
-
async with app_with_restricted_authz._lifespan(app_with_restricted_authz.fastapi):
|
141
|
-
client = PlanarTestClient(app_with_restricted_authz)
|
142
|
-
principal = Principal(sub="test_user", role="admin") # type: ignore
|
143
|
-
token = set_principal(principal)
|
144
|
-
|
145
|
-
# Call the workflow management endpoint to list workflows
|
146
|
-
response = await client.get("/planar/v1/workflows/")
|
147
|
-
assert_workflow_list(response)
|
148
|
-
|
149
|
-
clear_principal(token)
|
150
|
-
|
151
|
-
|
152
|
-
async def test_list_workflows_with_restricted_authz_and_wrong_role(
|
153
|
-
app_with_restricted_authz,
|
154
|
-
):
|
155
|
-
"""
|
156
|
-
Test that the workflow management router correctly forbids access to workflows list.
|
157
|
-
"""
|
158
|
-
|
159
|
-
async with app_with_restricted_authz._lifespan(app_with_restricted_authz.fastapi):
|
160
|
-
client = PlanarTestClient(app_with_restricted_authz)
|
161
|
-
principal = Principal(sub="test_user", role="test_role") # type: ignore
|
162
|
-
token = set_principal(principal)
|
163
|
-
|
164
|
-
# Call the workflow management endpoint to list workflows
|
165
|
-
response = await client.get("/planar/v1/workflows/")
|
166
|
-
assert response.status_code == HTTPStatus.FORBIDDEN
|
167
|
-
|
168
|
-
clear_principal(token)
|