227 lines
7.9 KiB
Python
Raw Normal View History

2026-07-07 15:28:28 +02:00
# retoor <retoor@molodetz.nl>
import time
import requests
from tests.conftest import BASE_URL, login_user
from devplacepy.database import (
get_table,
get_primary_admin_uid,
invalidate_admins_cache,
refresh_snapshot,
)
from devplacepy.utils import clear_user_cache
_counter = [0]
def _make_admin():
_counter[0] += 1
name = f"ecm{int(time.time() * 1000)}{_counter[0]}"
password = "secret123"
requests.post(
f"{BASE_URL}/auth/signup",
data={
"username": name,
"email": f"{name}@t.dev",
"password": password,
"confirm_password": password,
},
allow_redirects=True,
)
refresh_snapshot()
row = get_table("users").find_one(username=name)
get_table("users").update({"uid": row["uid"], "role": "Admin"}, ["uid"])
clear_user_cache(row["uid"])
invalidate_admins_cache()
return {
"email": f"{name}@t.dev",
"password": password,
"uid": row["uid"],
"api_key": row["api_key"],
}
def _demote_existing_admins():
existing = [r["uid"] for r in get_table("users").find(role="Admin")]
for uid in existing:
get_table("users").update({"uid": uid, "role": "Member"}, ["uid"])
invalidate_admins_cache()
return existing
def _restore_admins(uids):
for uid in uids:
get_table("users").update({"uid": uid, "role": "Admin"}, ["uid"])
invalidate_admins_cache()
def _create_project(api_key, title, is_private=False):
data = {
"title": title,
"description": "e2e container manage isolation",
"project_type": "software",
"status": "In Development",
}
if is_private:
data["is_private"] = "on"
r = requests.post(
f"{BASE_URL}/projects/create",
headers={"Accept": "application/json", "X-API-KEY": api_key},
data=data,
)
assert r.status_code == 200, r.text
return r.json()["data"]
def _insert_instance(project_uid, created_by):
uid = f"ecm-{int(time.time() * 1000000)}"
get_table("instances").insert(
{
"uid": uid,
"slug": uid,
"name": "e2e-manage-test",
"project_uid": project_uid,
"created_by": created_by,
"owner_uid": "",
"status": "stopped",
"container_id": "",
"workspace_dir": "",
"restart_policy": "never",
"deleted_at": None,
"deleted_by": None,
}
)
refresh_snapshot()
return uid
def _cleanup(inst_uid):
get_table("instances").delete(uid=inst_uid)
refresh_snapshot()
def test_admin_list_shows_view_only_for_non_owned_public_instance(page, app_server):
owner = _make_admin()
other = _make_admin()
project = _create_project(owner["api_key"], "E2E Manage List Public", is_private=False)
inst_uid = _insert_instance(project["uid"], owner["uid"])
try:
login_user(page, other)
page.goto(f"{BASE_URL}/admin/containers", wait_until="domcontentloaded")
row = page.locator(f"tr.cm-row[data-uid='{inst_uid}']")
row.wait_for(state="visible", timeout=15000)
assert "view only" in row.inner_text().lower()
assert row.locator("[data-cm-action='delete']").count() == 0
finally:
_cleanup(inst_uid)
def test_admin_list_shows_actions_for_owner(page, app_server):
owner = _make_admin()
project = _create_project(owner["api_key"], "E2E Manage List Owner", is_private=False)
inst_uid = _insert_instance(project["uid"], owner["uid"])
try:
login_user(page, owner)
page.goto(f"{BASE_URL}/admin/containers", wait_until="domcontentloaded")
row = page.locator(f"tr.cm-row[data-uid='{inst_uid}']")
row.wait_for(state="visible", timeout=15000)
assert row.locator("[data-cm-action='delete']").count() == 1
finally:
_cleanup(inst_uid)
def test_admin_list_excludes_others_private_project_instance(page, app_server):
owner = _make_admin()
other = _make_admin()
project = _create_project(owner["api_key"], "E2E Manage List Private", is_private=True)
inst_uid = _insert_instance(project["uid"], owner["uid"])
try:
login_user(page, other)
page.goto(f"{BASE_URL}/admin/containers", wait_until="domcontentloaded")
assert page.locator(f"tr.cm-row[data-uid='{inst_uid}']").count() == 0
finally:
_cleanup(inst_uid)
def test_admin_detail_page_view_only_hides_manage_controls(page, app_server):
owner = _make_admin()
other = _make_admin()
project = _create_project(owner["api_key"], "E2E Manage Detail Public", is_private=False)
inst_uid = _insert_instance(project["uid"], owner["uid"])
try:
login_user(page, other)
page.goto(f"{BASE_URL}/admin/containers/{inst_uid}", wait_until="domcontentloaded")
actions = page.locator("#ci-actions")
actions.wait_for(state="visible")
assert "view only" in actions.inner_text().lower()
assert page.locator("#ci-term-toggle").count() == 0
assert page.locator("[data-modal='ci-schedule-modal']").count() == 0
assert page.locator("a:has-text('Edit configuration')").count() == 0
finally:
_cleanup(inst_uid)
def test_admin_detail_page_owner_sees_manage_controls(page, app_server):
owner = _make_admin()
project = _create_project(owner["api_key"], "E2E Manage Detail Owner", is_private=False)
inst_uid = _insert_instance(project["uid"], owner["uid"])
try:
login_user(page, owner)
page.goto(f"{BASE_URL}/admin/containers/{inst_uid}", wait_until="domcontentloaded")
page.locator("[data-modal='ci-schedule-modal']").wait_for(state="visible")
assert page.locator("a:has-text('Edit configuration')").count() == 1
assert page.locator("#ci-term-toggle").count() == 1
finally:
_cleanup(inst_uid)
def test_admin_detail_page_404_for_non_viewer_on_private_project(page, app_server):
owner = _make_admin()
other = _make_admin()
project = _create_project(owner["api_key"], "E2E Manage Detail Private", is_private=True)
inst_uid = _insert_instance(project["uid"], owner["uid"])
try:
login_user(page, other)
page.goto(f"{BASE_URL}/admin/containers/{inst_uid}", wait_until="domcontentloaded")
assert page.is_visible("text=Not Found") or page.is_visible("text=404")
finally:
_cleanup(inst_uid)
def test_admin_edit_page_redirects_non_owner_to_detail(page, app_server):
owner = _make_admin()
other = _make_admin()
project = _create_project(owner["api_key"], "E2E Manage Edit Redirect", is_private=False)
inst_uid = _insert_instance(project["uid"], owner["uid"])
try:
login_user(page, other)
page.goto(f"{BASE_URL}/admin/containers/{inst_uid}/edit", wait_until="domcontentloaded")
page.wait_for_url(f"**/admin/containers/{inst_uid}", wait_until="domcontentloaded")
finally:
_cleanup(inst_uid)
def test_primary_admin_sees_and_manages_others_private_instance(page, app_server):
restore = _demote_existing_admins()
try:
primary = _make_admin()
owner = _make_admin()
assert get_primary_admin_uid() == primary["uid"]
project = _create_project(
owner["api_key"], "E2E Manage Primary Private", is_private=True
)
inst_uid = _insert_instance(project["uid"], owner["uid"])
try:
login_user(page, primary)
page.goto(f"{BASE_URL}/admin/containers", wait_until="domcontentloaded")
row = page.locator(f"tr.cm-row[data-uid='{inst_uid}']")
row.wait_for(state="visible", timeout=15000)
assert row.locator("[data-cm-action='delete']").count() == 1
page.goto(f"{BASE_URL}/admin/containers/{inst_uid}", wait_until="domcontentloaded")
page.locator("a:has-text('Edit configuration')").wait_for(state="visible")
finally:
_cleanup(inst_uid)
finally:
_restore_admins(restore)