From 5025732d12f0c2ea6ce76798f424284202113261 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Mon, 13 Jul 2026 23:49:13 +0300 Subject: [PATCH] fix(tradein/audit): exclude /api/v1/admin/* from api_request events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Admin viewing the audit/analytics dashboards hits /api/v1/admin/* which the request-audit middleware logged as api_request — polluting top_paths and activity counts with the dashboards' own traffic. Skip api_request for admin paths; keep login (admin sign-in from an IP is still valid audit). --- tradein-mvp/backend/app/core/request_audit.py | 21 +++++++++------- .../backend/tests/test_request_audit.py | 24 +++++++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/tradein-mvp/backend/app/core/request_audit.py b/tradein-mvp/backend/app/core/request_audit.py index faa929a5..a217cbfd 100644 --- a/tradein-mvp/backend/app/core/request_audit.py +++ b/tradein-mvp/backend/app/core/request_audit.py @@ -40,14 +40,19 @@ class RequestAuditMiddleware(BaseHTTPMiddleware): ua = request.headers.get("user-agent") # Общий behavior/activity-поток — каждый authenticated API-запрос. - schedule_event( - event_type="api_request", - username=username, - ip=ip, - user_agent=ua, - path=path, - method=request.method, - ) + # /api/v1/admin/* исключаем: это ops-действия (просмотр самих + # дашбордов аудита/аналитики), а не поведение пилота — иначе + # запросы дашборда зашумляют top_paths и счётчики активности. + # login ниже логируем всегда (вход админа с IP — валидный аудит). + if not path.startswith("/api/v1/admin/"): + schedule_event( + event_type="api_request", + username=username, + ip=ip, + user_agent=ua, + path=path, + method=request.method, + ) # Дедуплицированный login/IP-audit сигнал — максимум раз в день # на (юзер, IP, устройство). diff --git a/tradein-mvp/backend/tests/test_request_audit.py b/tradein-mvp/backend/tests/test_request_audit.py index 074502f8..62bbf525 100644 --- a/tradein-mvp/backend/tests/test_request_audit.py +++ b/tradein-mvp/backend/tests/test_request_audit.py @@ -114,3 +114,27 @@ def test_audit_failure_does_not_break_response(client: TestClient) -> None: assert resp.status_code == 200 assert resp.json() == {"ok": True} + + +def test_admin_path_excluded_from_api_request_but_login_kept() -> None: + """/api/v1/admin/* — ops-действия (просмотр дашбордов аудита/аналитики), не + поведение пилота: api_request НЕ пишем (иначе дашборд зашумляет активность), + а login (вход админа с IP) остаётся валидным аудитом.""" + app = FastAPI() + app.add_middleware(RequestAuditMiddleware) + + @app.get("/api/v1/admin/analytics") + def analytics() -> dict[str, bool]: + return {"ok": True} + + with ( + patch("app.core.request_audit.schedule_event") as mock_schedule, + patch("app.core.request_audit.should_log_login", return_value=True), + ): + resp = TestClient(app).get( + "/api/v1/admin/analytics", headers={"X-Authenticated-User": "admin"} + ) + + assert resp.status_code == 200 + event_types = [c.kwargs["event_type"] for c in mock_schedule.call_args_list] + assert event_types == ["login"]