Cap uploads, GC empty boards, drop classic UI
Close residual audit P2: 5 MiB recording limit, opportunistic orphan board GC, and remove static/index.html.
This commit is contained in:
@@ -17,6 +17,8 @@ def client(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> TestClient:
|
||||
monkeypatch.setenv("STORK_COOKIE_SECURE", "false")
|
||||
monkeypatch.delenv("STORK_READONLY_BOARD_IDS", raising=False)
|
||||
monkeypatch.delenv("STORK_RL_BOARDS_PER_HOUR", raising=False)
|
||||
monkeypatch.delenv("STORK_MAX_UPLOAD_BYTES", raising=False)
|
||||
monkeypatch.delenv("STORK_ORPHAN_BOARD_HOURS", raising=False)
|
||||
|
||||
import stork.app as app_mod
|
||||
import stork.rate_limit as rl_mod
|
||||
|
||||
@@ -134,6 +134,69 @@ def test_recording_rejects_bad_magic(authed: TestClient) -> None:
|
||||
assert up.status_code == 400
|
||||
|
||||
|
||||
def test_recording_rejects_oversized(tmp_path, monkeypatch) -> None:
|
||||
monkeypatch.setenv("STORK_DATA", str(tmp_path / "data"))
|
||||
monkeypatch.setenv("STORK_INVITE_TOKEN", "test-invite-token")
|
||||
monkeypatch.setenv("STORK_ADMIN_TOKEN", "test-admin-token")
|
||||
monkeypatch.setenv("STORK_COOKIE_SECURE", "false")
|
||||
monkeypatch.setenv("STORK_MAX_UPLOAD_BYTES", "40")
|
||||
|
||||
import stork.app as app_mod
|
||||
import stork.rate_limit as rl
|
||||
|
||||
importlib.reload(rl)
|
||||
importlib.reload(app_mod)
|
||||
app_mod.limiter.reset()
|
||||
with TestClient(app_mod.app) as client:
|
||||
board = client.get("/api/resolve", params={"invite": "test-invite-token"}).json()
|
||||
client.post("/api/session", json={"board_id": board["id"], "display_name": "Ilia"})
|
||||
name = client.post("/api/names", json={"kind": "c1", "spelling": "Big"}).json()
|
||||
huge = b"\x1a\x45\xdf\xa3" + b"\x00" * 64
|
||||
up = client.post(
|
||||
f"/api/names/{name['id']}/recording/en",
|
||||
files={"file": ("voice.webm", huge, "audio/webm")},
|
||||
)
|
||||
assert up.status_code == 413
|
||||
app_mod.store.close()
|
||||
|
||||
|
||||
def test_orphan_empty_boards_gc(tmp_path, monkeypatch) -> None:
|
||||
monkeypatch.setenv("STORK_DATA", str(tmp_path / "data"))
|
||||
monkeypatch.setenv("STORK_INVITE_TOKEN", "test-invite-token")
|
||||
monkeypatch.setenv("STORK_ADMIN_TOKEN", "test-admin-token")
|
||||
monkeypatch.setenv("STORK_COOKIE_SECURE", "false")
|
||||
monkeypatch.setenv("STORK_ORPHAN_BOARD_HOURS", "1")
|
||||
|
||||
import time
|
||||
|
||||
import stork.app as app_mod
|
||||
import stork.rate_limit as rl
|
||||
|
||||
importlib.reload(rl)
|
||||
importlib.reload(app_mod)
|
||||
app_mod.limiter.reset()
|
||||
with TestClient(app_mod.app) as client:
|
||||
family = client.get("/api/resolve", params={"invite": "test-invite-token"}).json()
|
||||
orphan = client.post("/api/boards", json={"title": "Abandoned"}).json()
|
||||
orphan_id = orphan["id"]
|
||||
# Backdate orphan so it is past the 1h cutoff.
|
||||
with app_mod.store._lock:
|
||||
app_mod.store._conn.execute(
|
||||
"UPDATE boards SET created_at = ? WHERE id = ?",
|
||||
(time.time() - 7200, orphan_id),
|
||||
)
|
||||
app_mod.store._conn.commit()
|
||||
kept = client.post("/api/boards", json={"title": "Fresh"}).json()
|
||||
assert client.get(f"/api/boards/{orphan_id}").status_code == 404
|
||||
assert client.get(f"/api/boards/{kept['id']}").status_code == 200
|
||||
assert client.get(f"/api/boards/{family['id']}").status_code == 200
|
||||
app_mod.store.close()
|
||||
|
||||
|
||||
def test_classic_index_removed(client: TestClient) -> None:
|
||||
assert client.get("/static/index.html").status_code == 404
|
||||
|
||||
|
||||
def test_session_rejects_missing_board(client: TestClient) -> None:
|
||||
res = client.post("/api/session", json={"display_name": "Ilia", "board_id": "b_missing"})
|
||||
assert res.status_code == 404
|
||||
|
||||
Reference in New Issue
Block a user