iUUUUpdatexz

This commit is contained in:
2026-08-07 10:53:43 +02:00
parent b777a5b9d0
commit 21f6ae0615
57 changed files with 4050 additions and 165 deletions
+42
View File
@@ -181,3 +181,45 @@ def test_rate_limit_block_recorded(monkeypatch):
event_key="security.rate_limit.block", result="denied"
)
assert event is not None
def _member_with_null_is_active():
session, name = _member()
row = _db_user(name)
get_table("users").update({"uid": row["uid"], "is_active": None}, ["uid"])
refresh_snapshot()
return name, row
def test_login_works_when_is_active_was_never_written(seeded_db):
name, _row = _member_with_null_is_active()
response = requests.post(
f"{BASE_URL}/auth/login",
headers=JSON_audit_log,
data={"email": f"{name}@t.dev", "password": "secret123"},
allow_redirects=False,
)
assert response.status_code == 200, response.text[:300]
def test_api_key_works_when_is_active_was_never_written(seeded_db):
_name, row = _member_with_null_is_active()
response = requests.get(
f"{BASE_URL}/profile",
headers={**JSON_audit_log, "X-API-KEY": row["api_key"]},
allow_redirects=False,
)
assert response.status_code == 200, response.text[:300]
def test_an_explicitly_disabled_account_still_cannot_log_in(seeded_db):
session, name = _member()
row = _db_user(name)
get_table("users").update({"uid": row["uid"], "is_active": False}, ["uid"])
refresh_snapshot()
response = requests.get(
f"{BASE_URL}/profile",
headers={**JSON_audit_log, "X-API-KEY": row["api_key"]},
allow_redirects=False,
)
assert response.status_code == 401
+230
View File
@@ -0,0 +1,230 @@
# retoor <retoor@molodetz.nl>
import pytest
from devplacepy.content import can_manage_workspace, can_open_workspace
from devplacepy.database import get_table, init_db, set_setting
from devplacepy.services.containers import activity, store
from devplacepy.services.containers.workspace import (
flags,
naming,
provision,
quota,
tunnels,
)
from devplacepy.services.containers.workspace.provision import WorkspaceError
from tests.conftest import run_async
OWNER = "user-owner"
OTHER = "user-other"
@pytest.fixture(autouse=True)
def _workspace_db():
init_db()
set_setting("workspace_enabled", "1")
yield
for table in ("instances", "tunnels", "workspace_flags", "workspace_quota_rules"):
get_table(table).delete()
def _project(uid: str = "proj-ws") -> dict:
return {"uid": uid, "slug": "demo", "title": "Demo", "user_uid": OWNER}
def _instance(**overrides) -> dict:
row = {
"project_uid": "proj-ws",
"name": "ws-demo",
"status": "running",
"desired_state": "running",
"is_workspace": 1,
"workspace_owner_uid": OWNER,
"tunnel_name": naming.generate(),
"ports_json": '[{"host": 20500, "container": 8080, "proto": "tcp"}]',
}
row.update(overrides)
return store.create_instance(row)
def test_open_workspace_requires_enabled_setting():
set_setting("workspace_enabled", "0")
assert can_open_workspace(_project(), {"uid": OWNER, "role": "Member"}) is False
set_setting("workspace_enabled", "1")
assert can_open_workspace(_project(), {"uid": OWNER, "role": "Member"}) is True
def test_guest_can_never_open_workspace():
assert can_open_workspace(_project(), None) is False
assert can_open_workspace(_project(), {}) is False
def test_non_owner_member_cannot_open_workspace():
assert can_open_workspace(_project(), {"uid": OTHER, "role": "Member"}) is False
def test_admin_can_open_any_project_workspace():
assert can_open_workspace(_project(), {"uid": OTHER, "role": "Admin"}) is True
def test_owner_manages_own_workspace_without_admin():
instance = _instance()
assert can_manage_workspace(instance, _project(), {"uid": OWNER, "role": "Member"})
assert not can_manage_workspace(
instance, _project(), {"uid": OTHER, "role": "Member"}
)
def test_create_or_resume_is_idempotent():
project = _project()
user = {"uid": OWNER, "username": "owner"}
first = run_async(provision.ensure(project, user))
second = run_async(provision.ensure(project, user))
assert first["uid"] == second["uid"]
assert provision.count_for_owner(OWNER) == 1
def test_workspace_quota_blocks_beyond_limit():
set_setting("workspace_max_per_user", "1")
user = {"uid": OWNER, "username": "owner"}
run_async(provision.ensure(_project("p-a"), user))
with pytest.raises(WorkspaceError):
run_async(provision.ensure(_project("p-b"), user))
set_setting("workspace_max_per_user", "2")
def test_tunnel_revives_rather_than_duplicates():
instance = _instance()
first = tunnels.create(instance, "web", 8080, OWNER)
tunnels.soft_delete(first["uid"], OWNER)
assert tunnels.count_for_instance(instance["uid"]) == 0
revived = tunnels.create(instance, "web", 8080, OWNER)
assert revived["uid"] == first["uid"]
assert tunnels.count_for_instance(instance["uid"]) == 1
def test_tunnel_hostname_is_a_single_dns_label():
instance = _instance()
row = tunnels.create(instance, "web", 3000, OWNER)
host = row["hostname"]
suffix = "." + naming.domain()
assert host.endswith(suffix)
label = host[: -len(suffix)]
assert "." not in label
assert naming.is_valid_label(label)
def test_suspend_stops_tunnels_without_deleting_them():
instance = _instance()
tunnels.create(instance, "web", 8080, OWNER)
provision.suspend(instance, "admin-uid", "abuse")
rows = tunnels.list_for_instance(instance["uid"])
assert rows and rows[0]["status"] == "suspended"
refreshed = store.get_instance(instance["uid"])
assert refreshed["suspended_at"]
provision.unsuspend(refreshed)
assert tunnels.list_for_instance(instance["uid"])[0]["status"] == "pending"
def test_suspended_workspace_cannot_resume():
instance = _instance()
provision.suspend(instance, "admin-uid", "abuse")
with pytest.raises(WorkspaceError):
provision.resume(store.get_instance(instance["uid"]))
def test_flags_are_idempotent_while_open():
instance = _instance()
first = flags.raise_flag(instance, flags.KIND_EGRESS, "warn", "a", 1.0, 0.5)
second = flags.raise_flag(instance, flags.KIND_EGRESS, "warn", "b", 2.0, 0.5)
assert first["uid"] == second["uid"]
assert len(flags.list_flags(instance_uid=instance["uid"])) == 1
flags.clear_flag(instance["uid"], flags.KIND_EGRESS, "admin")
assert flags.list_flags(instance_uid=instance["uid"]) == []
def test_activity_accumulates_egress_and_requests():
instance = _instance()
activity.forget(instance["uid"])
for _ in range(3):
activity.touch(instance["uid"], egress_bytes=100)
activity.flush(instance["uid"])
row = store.get_instance(instance["uid"])
assert row["egress_bytes"] == 300
assert row["request_count"] == 3
assert row["last_active_at"]
def test_quota_rule_overrides_only_its_owner():
get_table("workspace_quota_rules").insert(
{
"uid": "rule-x",
"owner_kind": "user",
"owner_id": OWNER,
"label": "power",
"max_workspaces": 7,
"deleted_at": None,
"deleted_by": None,
}
)
assert quota.resolve(OWNER).max_workspaces == 7
assert quota.resolve(OTHER).max_workspaces == quota.resolve().max_workspaces
def test_workspace_env_contract_is_complete():
from devplacepy.services.containers import api
instance = _instance()
env = api.workspace_env(instance, "https://example.test")
for key in (
"DEVPLACE_WORKSPACE",
"DEVPLACE_WORKSPACE_UID",
"DEVPLACE_TUNNEL_NAME",
"DEVPLACE_TUNNEL_DOMAIN",
"DEVPLACE_TUNNEL_MANIFEST",
"VSCODE_PROXY_URI",
"DEVPLACE_EDITOR_PORT",
"DEVPLACE_QUOTA_DISK_MB",
"DEVPLACE_RETENTION_DAYS",
):
assert key in env, key
assert all(isinstance(value, str) for value in env.values())
assert "{{port}}" in env["VSCODE_PROXY_URI"]
def test_non_workspace_instance_gets_no_workspace_env():
from devplacepy.services.containers import api
env = api.workspace_env({"is_workspace": 0}, "https://example.test")
assert env == {"DEVPLACE_WORKSPACE": ""}
def test_devii_workspace_tools_are_role_gated():
from devplacepy.services.devii.registry import CATALOG
names = {a.name for a in CATALOG.actions if a.handler == "workspace"}
admin_only = {
a.name for a in CATALOG.actions if a.handler == "workspace" and a.requires_admin
}
guest = {s["function"]["name"] for s in CATALOG.tool_schemas_for(False, False)}
member = {s["function"]["name"] for s in CATALOG.tool_schemas_for(True, False)}
admin = {s["function"]["name"] for s in CATALOG.tool_schemas_for(True, True)}
assert not (names & guest)
assert not ((names & member) & admin_only)
assert names <= admin
def test_every_confirm_gated_tool_declares_a_confirm_param():
from devplacepy.services.devii.actions.dispatcher import CONFIRM_REQUIRED
from devplacepy.services.devii.registry import CATALOG
for action in CATALOG.actions:
if action.handler != "workspace" or action.name not in CONFIRM_REQUIRED:
continue
assert any(p.name == "confirm" for p in action.params), action.name
def test_tunnel_host_detection_never_matches_the_site():
assert naming.is_tunnel_host("abc." + naming.domain())
assert not naming.is_tunnel_host("pravda.education")
assert not naming.is_tunnel_host("")
+221
View File
@@ -0,0 +1,221 @@
# retoor <retoor@molodetz.nl>
import re
from uuid import uuid4
import pytest
import requests
from playwright.sync_api import expect
from devplacepy.database import get_table, set_setting
from devplacepy.services.containers import store
from devplacepy.services.containers.workspace import flags, naming
from devplacepy.utils import make_combined_slug
from tests.conftest import BASE_URL
@pytest.fixture(autouse=True)
def _workspaces_on():
previous = None
row = get_table("site_settings").find_one(key="workspace_enabled")
if row:
previous = row.get("value")
set_setting("workspace_enabled", "1")
try:
yield
finally:
set_setting("workspace_enabled", previous if previous is not None else "0")
instances = get_table("instances")
created = [r["uid"] for r in instances.find(is_workspace=1)]
for uid in created:
get_table("tunnels").delete(instance_uid=uid)
get_table("workspace_flags").delete(instance_uid=uid)
instances.delete(uid=uid)
def _row_for(user: dict) -> dict:
return get_table("users").find_one(username=user["username"])
def _project_for(owner_uid: str, title: str = "WS Project") -> dict:
uid = str(uuid4())
slug = make_combined_slug(title, uid)
row = {
"uid": uid,
"user_uid": owner_uid,
"title": title,
"description": "workspace host project",
"slug": slug,
"stars": 0,
"created_at": "2026-01-01T00:00:00+00:00",
"deleted_at": None,
"deleted_by": None,
}
get_table("projects").insert(row)
return row
def _workspace_for(project: dict, owner_uid: str, **overrides) -> dict:
payload = {
"project_uid": project["uid"],
"name": "ws-e2e",
"status": "running",
"desired_state": "running",
"is_workspace": 1,
"workspace_owner_uid": owner_uid,
"tunnel_name": naming.generate(),
"ports_json": '[{"host": 20777, "container": 8080, "proto": "tcp"}]',
}
payload.update(overrides)
return store.create_instance(payload)
def test_workspace_page_offers_creation_to_owner(alice):
page, user = alice
project = _project_for(_row_for(user)["uid"])
page.goto(
f"{BASE_URL}/projects/{project['slug']}/workspace",
wait_until="domcontentloaded",
)
page.locator(".workspace-page").wait_for(state="visible")
expect(page.locator("button:has-text('Open workspace')")).to_be_visible()
def test_workspace_page_shows_state_quota_and_tunnel_form(alice):
page, user = alice
project = _project_for(_row_for(user)["uid"], "WS Detail")
_workspace_for(project, _row_for(user)["uid"])
page.goto(
f"{BASE_URL}/projects/{project['slug']}/workspace",
wait_until="domcontentloaded",
)
page.locator(".workspace-summary").wait_for(state="visible")
expect(page.locator("[data-workspace-status]")).to_contain_text("running")
expect(page.locator(".workspace-meter").first).to_be_visible()
expect(page.locator(".workspace-tunnel-form")).to_be_visible()
expect(page.locator(".workspace-help")).to_contain_text("sudo")
def test_owner_can_add_and_remove_a_tunnel(alice):
page, user = alice
project = _project_for(_row_for(user)["uid"], "WS Tunnel")
_workspace_for(project, _row_for(user)["uid"])
url = f"{BASE_URL}/projects/{project['slug']}/workspace"
page.goto(url, wait_until="domcontentloaded")
page.locator(".workspace-tunnel-form input[name='container_port']").fill("8080")
page.locator(".workspace-tunnel-form button:has-text('Add tunnel')").click()
page.wait_for_url(url, wait_until="domcontentloaded")
tunnel = page.locator(".workspace-tunnel").first
tunnel.wait_for(state="visible")
expect(tunnel).to_contain_text(naming.domain())
page.locator(".workspace-tunnel button:has-text('Remove')").first.click()
page.locator(".dialog-confirm").wait_for(state="visible")
page.locator(".dialog-confirm").click()
page.wait_for_url(url, wait_until="domcontentloaded")
expect(page.locator(".workspace-tunnel-list")).to_contain_text("No tunnels yet")
def test_suspended_workspace_shows_reason_to_owner(alice):
page, user = alice
project = _project_for(_row_for(user)["uid"], "WS Suspended")
instance = _workspace_for(project, _row_for(user)["uid"])
store.update_instance(
instance["uid"],
{"suspended_at": "2026-01-01T00:00:00+00:00", "flag_reason": "sustained cpu"},
)
page.goto(
f"{BASE_URL}/projects/{project['slug']}/workspace",
wait_until="domcontentloaded",
)
banner = page.locator(".workspace-suspended")
banner.wait_for(state="visible")
expect(banner).to_contain_text("sustained cpu")
def test_open_flag_is_visible_to_the_owner(alice):
page, user = alice
project = _project_for(_row_for(user)["uid"], "WS Flagged")
instance = _workspace_for(project, _row_for(user)["uid"])
flags.raise_flag(
store.get_instance(instance["uid"]),
flags.KIND_EGRESS,
"warn",
"egress above the hourly ceiling",
2048.0,
1024.0,
)
page.goto(
f"{BASE_URL}/projects/{project['slug']}/workspace",
wait_until="domcontentloaded",
)
flag = page.locator(".workspace-flag").first
flag.wait_for(state="visible")
expect(flag).to_contain_text("egress above the hourly ceiling")
def test_guest_cannot_reach_the_workspace_page(page):
project = _project_for(str(uuid4()), "WS Guest")
response = requests.get(
f"{BASE_URL}/projects/{project['slug']}/workspace",
allow_redirects=False,
)
assert response.status_code in (303, 401, 404)
def test_non_owner_member_is_refused(bob):
page, user = bob
project = _project_for(str(uuid4()), "WS Foreign")
page.goto(
f"{BASE_URL}/projects/{project['slug']}/workspace",
wait_until="domcontentloaded",
)
assert not page.locator(".workspace-summary").count()
def test_admin_console_lists_and_suspends_a_workspace(alice):
page, user = alice
project = _project_for(_row_for(user)["uid"], "WS Admin")
instance = _workspace_for(project, _row_for(user)["uid"])
page.goto(f"{BASE_URL}/admin/workspaces", wait_until="domcontentloaded")
row = page.locator(f"tr[data-workspace-uid='{instance['uid']}']")
row.wait_for(state="visible")
expect(row).to_contain_text("ws-e2e")
row.locator("input[name='reason']").fill("policy breach")
row.locator("button:has-text('Suspend')").click()
page.wait_for_url(f"{BASE_URL}/admin/workspaces", wait_until="domcontentloaded")
refreshed = store.get_instance(instance["uid"])
assert refreshed["suspended_at"]
row = page.locator(f"tr[data-workspace-uid='{instance['uid']}']")
expect(row).to_contain_text("suspended")
row.locator("button:has-text('Unsuspend')").click()
page.wait_for_url(f"{BASE_URL}/admin/workspaces", wait_until="domcontentloaded")
assert not store.get_instance(instance["uid"])["suspended_at"]
def test_admin_console_raises_and_resolves_a_flag(alice):
page, user = alice
project = _project_for(_row_for(user)["uid"], "WS Flag Admin")
instance = _workspace_for(project, _row_for(user)["uid"])
page.goto(f"{BASE_URL}/admin/workspaces", wait_until="domcontentloaded")
row = page.locator(f"tr[data-workspace-uid='{instance['uid']}']")
row.wait_for(state="visible")
row.locator("input[name='detail']").fill("manual review")
row.locator("button:has-text('Flag')").click()
page.wait_for_url(f"{BASE_URL}/admin/workspaces", wait_until="domcontentloaded")
assert flags.list_flags(instance_uid=instance["uid"])
page.locator("button:has-text('Resolve')").first.click()
page.wait_for_url(f"{BASE_URL}/admin/workspaces", wait_until="domcontentloaded")
assert not flags.list_flags(instance_uid=instance["uid"])
def test_workspaces_sidebar_link_is_present_for_admin(alice):
page, user = alice
page.goto(f"{BASE_URL}/admin/workspaces", wait_until="domcontentloaded")
link = page.locator(".sidebar-link:has-text('Workspaces')")
link.wait_for(state="visible")
expect(link).to_have_class(re.compile("active"))
+26
View File
@@ -67,3 +67,29 @@ def test_primary_admin_skips_deactivated_and_deleted_founders(local_db):
for uid, _, _, _ in seeded:
users.delete(uid=uid)
invalidate_admins_cache()
def test_account_with_a_null_is_active_counts_as_active(local_db):
from devplacepy.database import is_account_active
assert is_account_active({"is_active": None}) is True
def test_account_without_an_is_active_column_counts_as_active(local_db):
from devplacepy.database import is_account_active
assert is_account_active({}) is True
def test_an_explicitly_disabled_account_is_not_active(local_db):
from devplacepy.database import is_account_active
assert is_account_active({"is_active": False}) is False
assert is_account_active({"is_active": 0}) is False
def test_an_enabled_account_is_active(local_db):
from devplacepy.database import is_account_active
assert is_account_active({"is_active": True}) is True
assert is_account_active({"is_active": 1}) is True