Archived
Polish KarlDNS production UI and docs
This commit is contained in:
1 parent
ca92dc211a
commit
5beee0e5c6
61 files changed
+1566
-523
No files matched your search
+66
-13
@@ -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)}
|
||||
|
||||
Reference in new issue
Block a user