diff --git a/backend/app/api/v1/events.py b/backend/app/api/v1/events.py index 890f0ce..ad006a5 100644 --- a/backend/app/api/v1/events.py +++ b/backend/app/api/v1/events.py @@ -154,8 +154,10 @@ def list_events( stmt = stmt.where(Event.severity == severity) count_stmt = count_stmt.where(Event.severity == severity) if type: - stmt = stmt.where(Event.type == type) - count_stmt = count_stmt.where(Event.type == type) + normalized = type.strip() + if normalized: + stmt = stmt.where(Event.type.ilike(f"{normalized}%")) + count_stmt = count_stmt.where(Event.type.ilike(f"{normalized}%")) if host_id is not None: stmt = stmt.where(Event.host_id == host_id) count_stmt = count_stmt.where(Event.host_id == host_id) diff --git a/backend/app/services/rdg_display.py b/backend/app/services/rdg_display.py index 14e9049..f00eb86 100644 --- a/backend/app/services/rdg_display.py +++ b/backend/app/services/rdg_display.py @@ -69,7 +69,7 @@ def _windows_event_label(event: Event) -> str: if win_id is None: return "" text = str(win_id).strip() - return f"Win{text}" if text else "" + return f"event {text}" if text else "" def _action_label(event: Event) -> str: diff --git a/backend/app/version.py b/backend/app/version.py index 5d62f10..576e16c 100644 --- a/backend/app/version.py +++ b/backend/app/version.py @@ -1,5 +1,5 @@ """Единый источник версии SAC (API, health, логи, OpenAPI).""" APP_NAME = "Security Alert Center" -APP_VERSION = "0.3.1" +APP_VERSION = "0.3.2" APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}" diff --git a/backend/tests/test_events_list_filter.py b/backend/tests/test_events_list_filter.py new file mode 100644 index 0000000..f9d48d1 --- /dev/null +++ b/backend/tests/test_events_list_filter.py @@ -0,0 +1,54 @@ +"""Tests for GET /api/v1/events filters.""" + +import uuid + +VALID_RDG = { + "schema_version": "1.0", + "occurred_at": "2026-05-27T10:00:00+03:00", + "source": {"product": "rdp-login-monitor", "product_version": "1.2.3-SAC"}, + "host": {"hostname": "gw-filter-test", "os_family": "windows"}, + "category": "auth", + "severity": "info", + "title": "RDG", + "summary": "pytest", +} + + +def _ingest(client, auth_headers, *, event_type: str) -> str: + event_id = str(uuid.uuid4()) + payload = {**VALID_RDG, "event_id": event_id, "type": event_type} + assert client.post("/api/v1/events", json=payload, headers=auth_headers).status_code == 201 + return event_id + + +def test_events_type_filter_prefix(client, auth_headers, jwt_headers): + success_id = _ingest(client, auth_headers, event_type="rdg.connection.success") + disconnected_id = _ingest(client, auth_headers, event_type="rdg.connection.disconnected") + other_id = _ingest(client, auth_headers, event_type="rdp.login.success") + + listed = client.get( + "/api/v1/events", + headers=jwt_headers, + params={"type": "rdg.connection", "hostname": "gw-filter-test", "page_size": 50}, + ) + assert listed.status_code == 200 + body = listed.json() + ids = {row["event_id"] for row in body["items"]} + assert success_id in ids + assert disconnected_id in ids + assert other_id not in ids + + +def test_events_type_filter_exact_still_works(client, auth_headers, jwt_headers): + success_id = _ingest(client, auth_headers, event_type="rdg.connection.success") + disconnected_id = _ingest(client, auth_headers, event_type="rdg.connection.disconnected") + + listed = client.get( + "/api/v1/events", + headers=jwt_headers, + params={"type": "rdg.connection.success", "hostname": "gw-filter-test", "page_size": 50}, + ) + assert listed.status_code == 200 + ids = {row["event_id"] for row in listed.json()["items"]} + assert success_id in ids + assert disconnected_id not in ids diff --git a/backend/tests/test_health.py b/backend/tests/test_health.py index b792ae5..5442deb 100644 --- a/backend/tests/test_health.py +++ b/backend/tests/test_health.py @@ -4,6 +4,6 @@ from app.version import APP_NAME, APP_VERSION, APP_VERSION_LABEL def test_version_constants(): - assert APP_VERSION == "0.3.1" + assert APP_VERSION == "0.3.2" assert APP_NAME == "Security Alert Center" - assert APP_VERSION_LABEL == "Security Alert Center v.0.3.1" + assert APP_VERSION_LABEL == "Security Alert Center v.0.3.2" diff --git a/backend/tests/test_rdg_display.py b/backend/tests/test_rdg_display.py index 791446b..5d13fc7 100644 --- a/backend/tests/test_rdg_display.py +++ b/backend/tests/test_rdg_display.py @@ -85,6 +85,7 @@ def test_build_rdg_display_title_and_path(db_session, monkeypatch): assert display.qwinsta_enabled is True assert "papatramp" in display.summary assert "шлюз K6A-DC3" in display.summary + assert "event 302" in display.title def test_event_to_summary_enriches_rdg(db_session, monkeypatch): diff --git a/frontend/src/version.ts b/frontend/src/version.ts index 3da26e5..ce9ef64 100644 --- a/frontend/src/version.ts +++ b/frontend/src/version.ts @@ -1,4 +1,4 @@ /** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */ export const APP_NAME = "Security Alert Center"; -export const APP_VERSION = "0.3.1"; +export const APP_VERSION = "0.3.2"; export const APP_VERSION_LABEL = `${APP_NAME} v.${APP_VERSION}`; diff --git a/frontend/src/views/EventsView.vue b/frontend/src/views/EventsView.vue index 76a452f..b93ca4d 100644 --- a/frontend/src/views/EventsView.vue +++ b/frontend/src/views/EventsView.vue @@ -9,7 +9,7 @@ - +