fix: persist workspace Python environments
This commit is contained in:
+7
-1
@@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
|
||||
from agent_platform.auth import decode_openwebui_identity, verify_service_bearer
|
||||
from agent_platform.auth import UserIdentity, decode_openwebui_identity, issue_internal_identity, verify_service_bearer
|
||||
|
||||
|
||||
def test_signed_identity_is_verified(identity_jwt: str, settings) -> None:
|
||||
@@ -18,6 +18,12 @@ def test_invalid_identity_is_rejected(settings) -> None:
|
||||
assert error.value.status_code == 401
|
||||
|
||||
|
||||
def test_internal_identity_can_be_reissued_from_verified_claims(settings) -> None:
|
||||
expected = UserIdentity("user-123", "user@example.test", "Test User", "user")
|
||||
token = issue_internal_identity(expected, settings.openwebui_forward_jwt_secret)
|
||||
assert decode_openwebui_identity(token, settings.openwebui_forward_jwt_secret) == expected
|
||||
|
||||
|
||||
def test_service_bearer_uses_exact_match() -> None:
|
||||
verify_service_bearer("Bearer expected", "expected")
|
||||
with pytest.raises(HTTPException) as error:
|
||||
|
||||
@@ -36,6 +36,31 @@ async def test_real_docker_workspaces_are_isolated(settings) -> None:
|
||||
escaped = await provider.exec(users[0], "test ! -e /var/run/docker.sock", ".", 10)
|
||||
assert escaped.ok
|
||||
|
||||
environment = await provider.exec(
|
||||
users[0],
|
||||
'test "$HOME" = /workspace/.agent/home'
|
||||
' && test "$PYTHONUSERBASE" = /workspace/.agent/home/.local'
|
||||
' && case "$PATH" in /workspace/.venv/bin:*) exit 0;; *) exit 1;; esac',
|
||||
".",
|
||||
10,
|
||||
)
|
||||
assert environment.ok, environment.output
|
||||
virtualenv = await provider.exec(
|
||||
users[0],
|
||||
"python3 -m venv .venv && .venv/bin/python -m pip --version",
|
||||
".",
|
||||
30,
|
||||
)
|
||||
assert virtualenv.ok, virtualenv.output
|
||||
assert "/workspace/.venv/" in virtualenv.output
|
||||
hidden = await provider.list_files(users[0], ".", 4, 100)
|
||||
assert ".agent" not in hidden.output
|
||||
assert ".venv" not in hidden.output
|
||||
|
||||
piped_failure = await provider.exec(users[0], "false | tail -n 1", ".", 10)
|
||||
assert not piped_failure.ok
|
||||
assert piped_failure.exit_code == 1
|
||||
|
||||
git_init = "git init -q && git config user.email test@example.invalid && git config user.name Integration"
|
||||
assert (await provider.exec(users[0], git_init, ".", 10)).ok
|
||||
assert (await provider.write_file(users[0], "tracked.txt", "before\n")).ok
|
||||
@@ -64,6 +89,17 @@ async def test_real_docker_workspaces_are_isolated(settings) -> None:
|
||||
assert polled.exit_code == 0
|
||||
assert "background-done" in polled.output
|
||||
|
||||
failed = await provider.start_process(users[0], "false | tail -n 1", ".")
|
||||
failed_process_id = failed.metadata["process_id"]
|
||||
failed_poll = await provider.poll_process(users[0], failed_process_id)
|
||||
for _ in range(20):
|
||||
if not failed_poll.metadata.get("running"):
|
||||
break
|
||||
await asyncio.sleep(0.1)
|
||||
failed_poll = await provider.poll_process(users[0], failed_process_id)
|
||||
assert not failed_poll.ok
|
||||
assert failed_poll.exit_code == 1
|
||||
|
||||
container = client.containers.get(workspace_ref(users[0]).container_name)
|
||||
container.reload()
|
||||
second_container = client.containers.get(workspace_ref(users[1]).container_name)
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import cast
|
||||
|
||||
import httpx
|
||||
|
||||
from agent_platform.auth import UserIdentity, decode_openwebui_identity
|
||||
from agent_platform.runtime.tools import ToolContext, ToolRegistry
|
||||
from agent_platform.store import RuntimeStore
|
||||
|
||||
|
||||
async def test_gateway_call_uses_a_fresh_identity_token(settings) -> None:
|
||||
captured: dict[str, str] = {}
|
||||
|
||||
async def handle(request: httpx.Request) -> httpx.Response:
|
||||
captured["authorization"] = request.headers["Authorization"]
|
||||
captured["identity"] = request.headers["X-OpenWebUI-User-Jwt"]
|
||||
return httpx.Response(200, json={"ok": True, "output": "ready"})
|
||||
|
||||
identity = UserIdentity("user-123", "user@example.test", "Test User", "user")
|
||||
async with httpx.AsyncClient(transport=httpx.MockTransport(handle)) as client:
|
||||
registry = ToolRegistry(settings, cast(RuntimeStore, None), client=client)
|
||||
result = await registry.execute(
|
||||
"workspace_status",
|
||||
{},
|
||||
ToolContext(identity=identity, chat_id="chat-123"),
|
||||
)
|
||||
|
||||
assert result["ok"] is True
|
||||
assert captured["authorization"] == f"Bearer {settings.internal_gateway_key}"
|
||||
assert decode_openwebui_identity(captured["identity"], settings.openwebui_forward_jwt_secret) == identity
|
||||
Reference in New Issue
Block a user