fix: skip alerts for hidden event types, show them on host card (0.4.7)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -143,14 +143,22 @@ def list_events(
|
||||
type: str | None = None,
|
||||
host_id: int | None = None,
|
||||
hostname: str | None = None,
|
||||
include_hidden: bool = False,
|
||||
from_time: str | None = Query(None, alias="from"),
|
||||
to_time: str | None = Query(None, alias="to"),
|
||||
q: str | None = None,
|
||||
db: Session = Depends(get_db),
|
||||
_user: str = Depends(get_current_user),
|
||||
) -> EventListResponse:
|
||||
if include_hidden and host_id is None:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="include_hidden requires host_id",
|
||||
)
|
||||
hidden = get_hidden_event_types(db)
|
||||
type_filter = visibility_type_filter(hidden)
|
||||
if include_hidden and host_id is not None:
|
||||
type_filter = None
|
||||
stmt = select(Event).join(Host).options(joinedload(Event.host))
|
||||
count_stmt = select(func.count()).select_from(Event).join(Host)
|
||||
if type_filter is not None:
|
||||
@@ -347,14 +355,11 @@ def get_event(
|
||||
db: Session = Depends(get_db),
|
||||
_user: str = Depends(get_current_user),
|
||||
) -> EventDetail:
|
||||
hidden = get_hidden_event_types(db)
|
||||
event = db.scalar(
|
||||
select(Event).where(Event.id == event_db_id).options(joinedload(Event.host))
|
||||
)
|
||||
if event is None:
|
||||
raise HTTPException(status_code=404, detail="Event not found")
|
||||
if event.type in hidden:
|
||||
raise HTTPException(status_code=404, detail="Event not found")
|
||||
base = event_to_summary(event, db)
|
||||
return EventDetail(
|
||||
**base.model_dump(),
|
||||
|
||||
@@ -26,6 +26,14 @@ def show_in_events_for(event_type: str, *, hidden: frozenset[str]) -> bool:
|
||||
return event_type not in hidden
|
||||
|
||||
|
||||
def event_type_notifications_enabled(event_type: str, db: Session | None) -> bool:
|
||||
"""Outbound alerts (Telegram/push/email/webhook) only for types visible in events UI."""
|
||||
if db is None:
|
||||
return True
|
||||
hidden = get_hidden_event_types(db)
|
||||
return show_in_events_for(event_type, hidden=hidden)
|
||||
|
||||
|
||||
def visibility_type_filter(hidden: frozenset[str]) -> ColumnElement[bool] | None:
|
||||
if not hidden:
|
||||
return None
|
||||
|
||||
@@ -8,6 +8,7 @@ from app.models import Event, Problem
|
||||
from app.services import email_notify, mobile_notify, telegram_notify, webhook_notify
|
||||
from app.services.notification_cooldown import should_notify_event, should_notify_problem
|
||||
from app.services.notification_policy import get_effective_notification_policy
|
||||
from app.services.event_type_visibility import event_type_notifications_enabled
|
||||
from app.services.host_health import HEARTBEAT_TYPE
|
||||
from app.services.notification_severity import severity_meets_minimum
|
||||
|
||||
@@ -29,6 +30,17 @@ def _event_telegram_via_agent(event: Event) -> bool:
|
||||
return via == "agent"
|
||||
|
||||
|
||||
def _skip_notifications_for_hidden_event(event: Event, db: Session | None) -> bool:
|
||||
if event_type_notifications_enabled(event.type, db):
|
||||
return False
|
||||
logger.info(
|
||||
"notify skipped hidden event type=%s event_id=%s",
|
||||
event.type,
|
||||
event.event_id,
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
def _dispatch_event_channels(event: Event, *, db: Session | None, policy) -> None:
|
||||
if policy.use_telegram:
|
||||
telegram_notify.notify_event(event, db=db, apply_policy_gate=False)
|
||||
@@ -55,6 +67,8 @@ def notify_event(event: Event, *, db: Session | None = None) -> None:
|
||||
# Heartbeat — только для UI/статуса хоста, не для Telegram/email/push.
|
||||
if event.type == HEARTBEAT_TYPE:
|
||||
return
|
||||
if _skip_notifications_for_hidden_event(event, db):
|
||||
return
|
||||
policy = get_effective_notification_policy(db)
|
||||
if not severity_meets_minimum(event.severity, policy.min_severity):
|
||||
return
|
||||
@@ -89,6 +103,8 @@ def notify_daily_report(event: Event, *, db: Session | None = None) -> None:
|
||||
|
||||
При UseSAC=dual агент шлёт TG сам (telegram_via=agent) — SAC не дублирует.
|
||||
"""
|
||||
if _skip_notifications_for_hidden_event(event, db):
|
||||
return
|
||||
policy = get_effective_notification_policy(db)
|
||||
if not should_notify_event(event, db):
|
||||
return
|
||||
@@ -97,6 +113,8 @@ def notify_daily_report(event: Event, *, db: Session | None = None) -> None:
|
||||
|
||||
def notify_lifecycle(event: Event, *, db: Session | None = None) -> None:
|
||||
"""Старт/стоп/reload агента — всегда в каналы SAC (кроме TG, если telegram_via=agent)."""
|
||||
if _skip_notifications_for_hidden_event(event, db):
|
||||
return
|
||||
policy = get_effective_notification_policy(db)
|
||||
if not should_notify_event(event, db):
|
||||
return
|
||||
@@ -108,6 +126,8 @@ def notify_auth_login(event: Event, *, db: Session | None = None) -> None:
|
||||
|
||||
При UseSAC=dual агент шлёт TG сам (telegram_via=agent) — SAC не дублирует.
|
||||
"""
|
||||
if _skip_notifications_for_hidden_event(event, db):
|
||||
return
|
||||
policy = get_effective_notification_policy(db)
|
||||
if not should_notify_event(event, db):
|
||||
return
|
||||
@@ -116,6 +136,8 @@ def notify_auth_login(event: Event, *, db: Session | None = None) -> None:
|
||||
|
||||
def notify_rdg_connection(event: Event, *, db: Session | None = None) -> None:
|
||||
"""RD Gateway 302/303 — ingest всегда; Telegram SAC вне min_severity (как auth login)."""
|
||||
if _skip_notifications_for_hidden_event(event, db):
|
||||
return
|
||||
policy = get_effective_notification_policy(db)
|
||||
if not should_notify_event(event, db):
|
||||
return
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""Единый источник версии SAC (API, health, логи, OpenAPI)."""
|
||||
|
||||
APP_NAME = "Security Alert Center"
|
||||
APP_VERSION = "0.4.6"
|
||||
APP_VERSION = "0.4.7"
|
||||
APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}"
|
||||
|
||||
Reference in New Issue
Block a user