Files
tfaour d1f1968317
Build and push server image / test (push) Successful in 39s
Build and push server image / build-and-push (push) Failing after 1m59s
Build and push server image / deploy (push) Has been skipped
Log device-facing /frame/* requests in the server log
The admin log viewer only ever showed exceptions from device.py, not
successful requests -- no way to see a request that was slow-but-200,
or a device probing with a stale/wrong token. Adds a middleware that
logs method, path, device id (never the token), status, and wall time
for every /frame/* request.
2026-07-28 03:24:13 +00:00

76 lines
2.7 KiB
Python

"""Permission boundary + basic content checks for the admin log viewer
(routers/pages.py's admin_logs_page/admin_logs_download) -- see
CLAUDE.md's note that anything gated by an admin/permission check needs
a same-shape test: admin, non-admin logged in, logged out."""
from __future__ import annotations
import logging
from app.logging_setup import LOG_PATH
from app.models import Frame
from .conftest import login, make_user
def _setup_admin_and_user(client, db_session) -> None:
client.post("/setup", data={"username": "alice", "password": "hunter22"})
make_user(db_session, "bob")
def test_admin_can_view_logs(client, db_session):
_setup_admin_and_user(client, db_session)
login(client, "alice", "hunter22")
logging.getLogger("app.test").info("marker-line-for-test")
resp = client.get("/admin/logs")
assert resp.status_code == 200
assert "marker-line-for-test" in resp.text
def test_non_admin_forbidden_from_logs(client, db_session):
_setup_admin_and_user(client, db_session)
login(client, "bob")
resp = client.get("/admin/logs")
assert resp.status_code == 403
resp = client.get("/admin/logs/download")
assert resp.status_code == 403
def test_logged_out_redirected_from_logs_page(client, db_session):
_setup_admin_and_user(client, db_session)
client.cookies.clear() # /setup itself logs alice in
resp = client.get("/admin/logs")
assert resp.status_code == 303
assert resp.headers["location"] == "/login"
def test_admin_can_download_log_file(client, db_session):
_setup_admin_and_user(client, db_session)
login(client, "alice", "hunter22")
logging.getLogger("app.test").info("marker-line-for-download")
resp = client.get("/admin/logs/download")
assert resp.status_code == 200
assert b"marker-line-for-download" in resp.content
def test_device_requests_are_logged(client, db_session):
_setup_admin_and_user(client, db_session)
frame = db_session.get(Frame, 1)
frame.device_id = "aabbccddeeff"
db_session.commit()
resp = client.get(f"/frame/config?id={frame.device_id}&token={frame.device_token}")
assert resp.status_code == 200
login(client, "alice", "hunter22")
log_resp = client.get("/admin/logs")
# Jinja HTML-escapes the rendered <pre>, so "->" becomes "-&gt;".
assert f"GET /frame/config id={frame.device_id} -&gt; 200" in log_resp.text
def test_download_404s_before_any_log_written(client, db_session, monkeypatch):
_setup_admin_and_user(client, db_session)
login(client, "alice", "hunter22")
monkeypatch.setattr("app.routers.pages.LOG_PATH", LOG_PATH.parent / "does-not-exist.log")
resp = client.get("/admin/logs/download")
assert resp.status_code == 404