feat(tradein/admin): audit + analytics read API over user_events #2520

Merged
lekss361 merged 1 commit from feat/tradein-admin-audit-analytics-api into main 2026-07-13 20:26:59 +00:00
Owner

Что

Admin read-API над user_events — read-side фичи 2 (учёт входов/IP + что искали) и данные для дашборда фичи 3. Read-only, admin-only (централизованный гейт _ADMIN_API_RE в main.py, доп. auth-код не нужен).

Эндпоинты (/api/v1/admin/*)

  • GET /audit/accountslist[AccountSummary] — по строке на username: first/last_seen, distinct_ips, distinct_devices, login/request/search counts. ORDER BY last_seen DESC.
  • GET /audit/accounts/{username}AccountDrilldown — 4 списка: ips (IP × first/last/count), devices (user_agent × …), searches (estimate_request: адрес/площадь/комнаты/estimate_id/ip), recent_activity (последние 200 событий). Неизвестный username → 200 с пустыми списками (не 404).
  • GET /analytics?days=30AnalyticsDashboardsummary (total/distinct/24h), daily (time-series), top_searches (адреса), top_paths, by_account.

Корректность

  • Все SQL — параметризованный text(), CAST(:x AS type) (нет ::-trap), make_interval(days => CAST(:days AS int)).
  • Пустая таблица → нули/пустые списки, не ошибка.
  • days кламп 1..365; username валидируется (1..200).
  • Response-модели → OpenAPI codegen отдаст типы фронту.

Тесты

tests/test_audit_api.py11 passed, 1 skip (live-Postgres round-trip самоскип). Плюс test_account_quota/test_rbac/test_request_audit проходят (main.py include не сломал startup). ruff чисто, CAST-grep пуст.

Дальше: frontend-дашборды /admin/audit + /admin/analytics.

## Что Admin read-API над `user_events` — read-side фичи 2 (учёт входов/IP + что искали) и данные для дашборда фичи 3. Read-only, admin-only (централизованный гейт `_ADMIN_API_RE` в main.py, доп. auth-код не нужен). ## Эндпоинты (`/api/v1/admin/*`) - `GET /audit/accounts` → `list[AccountSummary]` — по строке на username: first/last_seen, distinct_ips, distinct_devices, login/request/search counts. ORDER BY last_seen DESC. - `GET /audit/accounts/{username}` → `AccountDrilldown` — 4 списка: `ips` (IP × first/last/count), `devices` (user_agent × …), `searches` (estimate_request: адрес/площадь/комнаты/estimate_id/ip), `recent_activity` (последние 200 событий). Неизвестный username → 200 с пустыми списками (не 404). - `GET /analytics?days=30` → `AnalyticsDashboard` — `summary` (total/distinct/24h), `daily` (time-series), `top_searches` (адреса), `top_paths`, `by_account`. ## Корректность - Все SQL — параметризованный `text()`, `CAST(:x AS type)` (нет `::`-trap), `make_interval(days => CAST(:days AS int))`. - Пустая таблица → нули/пустые списки, не ошибка. - `days` кламп 1..365; `username` валидируется (1..200). - Response-модели → OpenAPI codegen отдаст типы фронту. ## Тесты `tests/test_audit_api.py` — **11 passed, 1 skip** (live-Postgres round-trip самоскип). Плюс `test_account_quota/test_rbac/test_request_audit` проходят (main.py include не сломал startup). ruff чисто, CAST-grep пуст. Дальше: frontend-дашборды `/admin/audit` + `/admin/analytics`.
lekss361 added 1 commit 2026-07-13 20:25:19 +00:00
feat(tradein/admin): audit + analytics read API over user_events
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 9s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 1m0s
780af144c3
lekss361 merged commit 9fd6396fbc into main 2026-07-13 20:26:59 +00:00
lekss361 deleted branch feat/tradein-admin-audit-analytics-api 2026-07-13 20:26:59 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2520
No description provided.