Polish KarlDNS production UI and docs

This commit is contained in:
StasonJatham committed 2026-05-21 10:05:40 +02:00
1 parent ca92dc211a
commit 5beee0e5c6
61 files changed
+1566 -523

No files matched your search

+66 -13
View File
@@ -27,20 +27,24 @@ def test_admin_page_shows_operator_views_without_create_form(tmp_path: Path) ->
assert response.status_code == 200
assert response.headers["cache-control"] == "no-store"
assert '<link href="/admin.css?v=2" rel="stylesheet">' in response.text
assert '<script src="/admin-tables.js?v=2" defer></script>' in response.text
assert "Operator console" in response.text
assert "Generate credentials" not in response.text
assert 'action="/admin/accounts"' not in response.text
assert response.text.count("data-admin-table") == 4
assert response.text.count("data-table-search") == 4
assert response.text.count("data-table-page-size") == 4
assert response.text.count("data-table-pagination") == 4
assert response.text.count("data-admin-table") == 3
assert response.text.count("data-table-search") == 3
assert response.text.count("data-table-page-size") == 3
assert response.text.count("data-table-pagination") == 3
assert "admin-table-scroll" in response.text
assert "Scheduled cleanup" in response.text
assert "Scheduler state" in response.text
assert "database lease" in response.text
assert "Active credentials" in response.text
assert "Cleanup" in response.text
assert "Run now" in response.text
assert "Next run" in response.text
assert "Metrics" in response.text
assert "Blocked requests" in response.text
assert "Hostnames" in response.text
assert "Domain claims" in response.text
assert "Recent events" in response.text
assert "Update events" in response.text
assert "example.net" in response.text
@@ -89,10 +93,59 @@ def test_admin_records_and_events_are_paginated(tmp_path: Path) -> None:
assert len(records["items"]) == 1
assert events["limit"] == 1
assert events["offset"] == 1
assert "next_before" in events
assert events["total"] == 2
assert len(events["items"]) == 1
def test_admin_records_and_events_reject_excessive_offsets(tmp_path: Path) -> None:
app = make_app(DdnsSettings(database_path=tmp_path / "ddns.sqlite3", admin_password="admin"))
client = TestClient(app)
records = client.get("/records?offset=10001", auth=("admin", "admin"))
events = client.get("/events?offset=10001", auth=("admin", "admin"))
assert records.status_code == 422
assert events.status_code == 422
def test_update_events_page_orders_raw_and_rollup_events_in_sql(tmp_path: Path) -> None:
store = DdnsStore(tmp_path / "ddns.sqlite3")
store.log_update_event("raw-old.example.net", "203.0.113.1", None, "updated", "ok", "198.51.100.1")
store.log_update_event("raw-new.example.net", "203.0.113.2", None, "updated", "ok", "198.51.100.2")
store.log_update_rollup("rollup-mid.example.net", "203.0.113.3", None, "unchanged", "ok", "198.51.100.3")
with store.connect() as conn:
conn.execute("UPDATE update_events SET created_at = ? WHERE hostname = ?", ("2026-01-01T00:00:00+00:00", "raw-old.example.net"))
conn.execute("UPDATE update_events SET created_at = ? WHERE hostname = ?", ("2026-01-03T00:00:00+00:00", "raw-new.example.net"))
conn.execute(
"UPDATE update_event_rollups SET last_seen_at = ? WHERE hostname = ?",
("2026-01-02T00:00:00+00:00", "rollup-mid.example.net"),
)
page = store.list_update_events_page(limit=2, offset=1)
assert [event["hostname"] for event in page] == ["rollup-mid.example.net", "raw-old.example.net"]
def test_update_events_support_keyset_pagination(tmp_path: Path) -> None:
database_path = tmp_path / "ddns.sqlite3"
store = DdnsStore(database_path)
store.log_update_event("raw-old.example.net", "203.0.113.1", None, "updated", "ok", "198.51.100.1")
store.log_update_event("raw-new.example.net", "203.0.113.2", None, "updated", "ok", "198.51.100.2")
with store.connect() as conn:
conn.execute("UPDATE update_events SET created_at = ? WHERE hostname = ?", ("2026-01-01T00:00:00+00:00", "raw-old.example.net"))
conn.execute("UPDATE update_events SET created_at = ? WHERE hostname = ?", ("2026-01-02T00:00:00+00:00", "raw-new.example.net"))
app = make_app(DdnsSettings(database_path=database_path, admin_password="admin"))
client = TestClient(app)
first = client.get("/events?limit=1", auth=("admin", "admin")).json()
second = client.get(f"/events?limit=1&before={first['next_before']}", auth=("admin", "admin")).json()
assert first["items"][0]["hostname"] == "raw-new.example.net"
assert second["items"][0]["hostname"] == "raw-old.example.net"
def test_admin_posts_require_csrf(tmp_path: Path) -> None:
app = make_app(DdnsSettings(database_path=tmp_path / "ddns.sqlite3", admin_password="admin"))
client = TestClient(app)
@@ -150,7 +203,7 @@ def test_admin_can_rotate_links_and_password(tmp_path: Path) -> None:
data={"csrf": csrf, "hostname": "home.example.net", "action": "update"},
)
assert update.status_code == 200
assert "Update URL rotated" in update.text
assert "Update URL changed" in update.text
assert client.get(f"/u/{account['update_slug']}", params={"myip": "203.0.113.9"}).status_code == 404
management = client.post(
@@ -159,7 +212,7 @@ def test_admin_can_rotate_links_and_password(tmp_path: Path) -> None:
data={"csrf": csrf, "hostname": "home.example.net", "action": "management"},
)
assert management.status_code == 200
assert "Private status page rotated" in management.text
assert "Dashboard link changed" in management.text
assert "/m/" in management.text
password = client.post(
@@ -168,8 +221,8 @@ def test_admin_can_rotate_links_and_password(tmp_path: Path) -> None:
data={"csrf": csrf, "hostname": "home.example.net", "action": "password"},
)
assert password.status_code == 200
assert "Router password rotated" in password.text
assert "One-box update URL:" in password.text
assert "Router password changed" in password.text
assert "Full update URL:" in password.text
assert "/nic/update?" in password.text
assert "Kennwort (optional):" in password.text
statuses = {event["status"] for event in store.list_update_events_for_hostname("home.example.net", 10)}