Add publisher dashboard routes
All checks were successful
buildbot/nix-eval Build done.
buildbot/nix-build Build done.
buildbot/nix-effects Build done.

This commit is contained in:
Abel Luck 2026-06-02 10:18:59 +02:00
parent 96551c2788
commit e4a5246ab3
31 changed files with 1603 additions and 516 deletions

View file

@ -29,10 +29,10 @@ def _configure_trusted_auth(monkeypatch, tmp_path: Path, name: str) -> None:
monkeypatch.setenv("REPUBLISHER_DB_PATH", str(tmp_path / f"{name}.db"))
def _assert_datastar_shell(body: str) -> None:
def _assert_datastar_shell(body: str, *, static_prefix: str) -> None:
assert body.startswith("<!doctype html>")
assert 'id="js"' in body
assert 'src="/static/datastar@1.0.0-RC.8.js"' in body
assert f'src="{static_prefix}/static/datastar@1.0.0-RC.8.js"' in body
assert 'data-init="@post(window.location.pathname +' in body
assert '<main id="morph"' in body
assert "Connecting" in body
@ -62,7 +62,7 @@ def test_trusted_header_mode_rejects_admin_route_without_identity(
async def run() -> None:
client = create_app().test_client()
response = await client.get("/")
response = await client.get("/admin")
assert response.status_code == 401
@ -78,7 +78,7 @@ def test_trusted_header_mode_ignores_generic_forwarded_identity_headers(
client = create_app().test_client()
response = await client.get(
"/",
"/admin",
headers={
"X-Forwarded-User": "mallory",
"X-Forwarded-Email": "mallory@example.org",
@ -100,7 +100,7 @@ def test_trusted_header_mode_rejects_malformed_trusted_identity_headers(
client = create_app().test_client()
response = await client.get(
"/",
"/admin",
headers={
"X-Republisher-Auth-Role": "admin",
"X-Republisher-Auth-Provider": "gp",
@ -120,7 +120,7 @@ def test_trusted_header_mode_allows_admin_identity_on_admin_route(
async def run() -> None:
client = create_app().test_client()
response = await client.get("/", headers=_trusted_headers(role="admin"))
response = await client.get("/admin", headers=_trusted_headers(role="admin"))
assert response.status_code == 200
@ -135,7 +135,9 @@ def test_trusted_header_mode_rejects_publisher_identity_on_admin_route(
async def run() -> None:
client = create_app().test_client()
response = await client.get("/", headers=_trusted_headers(role="publisher"))
response = await client.get(
"/admin", headers=_trusted_headers(role="publisher")
)
assert response.status_code == 403
@ -152,7 +154,7 @@ def test_trusted_header_mode_rejects_admin_action_without_identity(
app.config["REPUB_LOG_DIR"] = tmp_path / "logs"
client = app.test_client()
response = await client.post("/actions/completed-executions/clear")
response = await client.post("/admin/actions/completed-executions/clear")
assert response.status_code == 401
@ -170,7 +172,7 @@ def test_trusted_header_mode_rejects_publisher_identity_on_admin_action(
client = app.test_client()
response = await client.post(
"/actions/completed-executions/clear",
"/admin/actions/completed-executions/clear",
headers=_trusted_headers(role="publisher"),
)
@ -194,12 +196,12 @@ def test_trusted_header_mode_allows_publisher_identity_on_publisher_route(
body = await response.get_data(as_text=True)
assert response.status_code == 200
_assert_datastar_shell(body)
_assert_datastar_shell(body, static_prefix="/publisher")
asyncio.run(run())
def test_trusted_header_mode_publisher_post_serves_hello_publishers_morph(
def test_trusted_header_mode_publisher_post_serves_publisher_dashboard_morph(
monkeypatch, tmp_path: Path
) -> None:
_configure_trusted_auth(monkeypatch, tmp_path, "publisher-post")
@ -220,7 +222,7 @@ def test_trusted_header_mode_publisher_post_serves_hello_publishers_morph(
assert raw_connection.headers["Content-Type"] == "text/event-stream"
assert b"event: datastar-patch-elements" in chunk
assert b'<main id="morph"' in chunk
assert b"Hello publishers" in chunk
assert b"Published feeds" in chunk
await connection.disconnect()
asyncio.run(run())
@ -258,12 +260,12 @@ def test_trusted_header_mode_allows_admin_identity_on_admin_publisher_alias(
body = await response.get_data(as_text=True)
assert response.status_code == 200
_assert_datastar_shell(body)
_assert_datastar_shell(body, static_prefix="/admin")
asyncio.run(run())
def test_trusted_header_mode_admin_publisher_post_serves_hello_publishers_morph(
def test_trusted_header_mode_admin_publisher_post_serves_publisher_dashboard_morph(
monkeypatch, tmp_path: Path
) -> None:
_configure_trusted_auth(monkeypatch, tmp_path, "admin-alias-post")
@ -284,7 +286,7 @@ def test_trusted_header_mode_admin_publisher_post_serves_hello_publishers_morph(
assert raw_connection.headers["Content-Type"] == "text/event-stream"
assert b"event: datastar-patch-elements" in chunk
assert b'<main id="morph"' in chunk
assert b"Hello publishers" in chunk
assert b"Published feeds" in chunk
await connection.disconnect()
asyncio.run(run())
@ -308,7 +310,79 @@ def test_trusted_header_mode_rejects_publisher_identity_on_admin_publisher_alias
asyncio.run(run())
def test_trusted_header_mode_keeps_static_assets_public(
def test_trusted_header_mode_allows_publisher_identity_on_publisher_run_action(
monkeypatch, tmp_path: Path
) -> None:
_configure_trusted_auth(monkeypatch, tmp_path, "publisher-run-action")
async def run() -> None:
client = create_app().test_client()
response = await client.post(
"/publisher/actions/jobs/999/run-now",
headers=_trusted_headers(role="publisher"),
)
assert response.status_code == 204
asyncio.run(run())
def test_trusted_header_mode_rejects_admin_identity_on_publisher_run_action(
monkeypatch, tmp_path: Path
) -> None:
_configure_trusted_auth(monkeypatch, tmp_path, "publisher-run-action-admin")
async def run() -> None:
client = create_app().test_client()
response = await client.post(
"/publisher/actions/jobs/999/run-now",
headers=_trusted_headers(role="admin"),
)
assert response.status_code == 403
asyncio.run(run())
def test_trusted_header_mode_allows_admin_identity_on_admin_publisher_run_action(
monkeypatch, tmp_path: Path
) -> None:
_configure_trusted_auth(monkeypatch, tmp_path, "admin-publisher-run-action")
async def run() -> None:
client = create_app().test_client()
response = await client.post(
"/admin/publisher/actions/jobs/999/run-now",
headers=_trusted_headers(role="admin"),
)
assert response.status_code == 204
asyncio.run(run())
def test_trusted_header_mode_rejects_publisher_identity_on_admin_publisher_run_action(
monkeypatch, tmp_path: Path
) -> None:
_configure_trusted_auth(monkeypatch, tmp_path, "admin-publisher-run-publisher")
async def run() -> None:
client = create_app().test_client()
response = await client.post(
"/admin/publisher/actions/jobs/999/run-now",
headers=_trusted_headers(role="publisher"),
)
assert response.status_code == 403
asyncio.run(run())
def test_trusted_header_mode_keeps_section_static_assets_public(
monkeypatch, tmp_path: Path
) -> None:
_configure_trusted_auth(monkeypatch, tmp_path, "static-public")
@ -316,9 +390,17 @@ def test_trusted_header_mode_keeps_static_assets_public(
async def run() -> None:
client = create_app().test_client()
response = await client.get("/static/datastar@1.0.0-RC.8.js")
for path in (
"/admin/static/datastar@1.0.0-RC.8.js",
"/publisher/static/datastar@1.0.0-RC.8.js",
):
response = await client.get(path)
assert response.status_code == 200
assert response.status_code == 200
root_response = await client.get("/static/datastar@1.0.0-RC.8.js")
assert root_response.status_code == 404
asyncio.run(run())