Files
cyclone/backend/tests/test_ack_endpoints_authenticated.py
T
tyler b80e40e7e9 fix(permissions): expose GET /api/acks, /api/ta1-acks, /api/277ca-acks
The PERMISSIONS matrix only listed the POST /api/acks entry (parse-999
ingest). The GET list + detail endpoints for 999 / TA1 / 277CA acks
were missing, so the matrix_gate (default-deny) returned 403 to every
authenticated role, breaking the 999 ACKs / TA1 / 277CA inbox pages.

Add the three GET entries as ALL_ROLES — they're read-only metadata
surfaces that every authenticated operator needs to see. Add a
regression test that logs in as admin via the public route and
exercises the matrix; the existing test_existing_endpoints_require_auth
suite only checks the unauthenticated 401 path, which is why this slipped
through.

Fixes the live-verification 'Couldn't load ACKs from the backend /
forbidden' error reported against the UI.
2026-06-24 17:51:44 -06:00

71 lines
2.2 KiB
Python

"""Regression: GET /api/acks, /api/ta1-acks, /api/277ca-acks must be reachable
for an authenticated admin. The PERMISSIONS matrix only listed the
``POST /api/acks`` (parse-999) entry, so the GET list/detail endpoints
returned 403 to admins and broke the Inbox / 999 ACKs pages on the UI.
This test exercises the matrix via the public login route — not by
flipping ``AUTH_DISABLED`` — so a missing ``("GET", "/api/<kind>-acks"):
ALL_ROLES`` entry would surface as 403.
"""
from __future__ import annotations
import pytest
from fastapi.testclient import TestClient
from sqlalchemy import delete
from cyclone.api import app
from cyclone.auth import users
from cyclone.db import Session as DbSession
from cyclone.db import SessionLocal, User
@pytest.fixture(autouse=True)
def _clear(monkeypatch):
monkeypatch.setattr("cyclone.auth.deps.AUTH_DISABLED", False)
with SessionLocal()() as db:
db.execute(delete(DbSession))
db.execute(delete(User))
db.commit()
yield
with SessionLocal()() as db:
db.execute(delete(DbSession))
db.execute(delete(User))
db.commit()
@pytest.fixture
def client():
return TestClient(app)
@pytest.fixture
def admin_client(client):
with SessionLocal()() as db:
users.create(db, username="admin", password="adminpassword1", role="admin")
resp = client.post(
"/api/auth/login",
json={"username": "admin", "password": "adminpassword1"},
)
assert resp.status_code == 200
return client
@pytest.mark.parametrize("path", [
"/api/acks",
"/api/acks/0",
"/api/ta1-acks",
"/api/ta1-acks/0",
"/api/277ca-acks",
"/api/277ca-acks/0",
])
def test_admin_can_list_and_detail_all_ack_kinds(admin_client, path):
resp = admin_client.get(path, headers={"Accept": "application/json"})
# 200 for the list endpoint (empty rows is fine), 404 for the detail
# of a non-existent id (the gate must let the request through).
assert resp.status_code in (200, 404), (
f"{path} returned {resp.status_code}: {resp.text}"
)
assert resp.status_code != 403, (
f"{path} returned 403 — PERMISSIONS matrix is missing a GET entry"
)