Files
OrbitWard/backend/app/api/alerts.py
T
2026-05-22 17:36:40 -06:00

107 lines
3.5 KiB
Python

from datetime import UTC, datetime, timedelta
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import select
from sqlalchemy.orm import Session
from app.auth.dependencies import get_current_user, require_role
from app.db.session import get_db
from app.models import AlertRule, Incident, User
from app.schemas.core import AlertRuleCreate, AlertRuleRead, AlertRuleUpdate, IncidentRead
router = APIRouter(tags=["alerts"])
@router.get("/alerts/rules", response_model=list[AlertRuleRead])
def list_alert_rules(_: User = Depends(get_current_user), db: Session = Depends(get_db)) -> list[AlertRule]:
return list(db.scalars(select(AlertRule).order_by(AlertRule.name)).all())
@router.post("/alerts/rules", response_model=AlertRuleRead)
def create_alert_rule(
payload: AlertRuleCreate,
_: User = Depends(require_role("admin")),
db: Session = Depends(get_db),
) -> AlertRule:
rule = AlertRule(**payload.model_dump())
db.add(rule)
db.commit()
db.refresh(rule)
return rule
@router.patch("/alerts/rules/{rule_id}", response_model=AlertRuleRead)
def update_alert_rule(
rule_id: int,
payload: AlertRuleUpdate,
_: User = Depends(require_role("admin")),
db: Session = Depends(get_db),
) -> AlertRule:
rule = db.get(AlertRule, rule_id)
if rule is None:
raise HTTPException(status_code=404, detail="Alert rule not found")
for field, value in payload.model_dump(exclude_unset=True).items():
setattr(rule, field, value)
db.commit()
db.refresh(rule)
return rule
@router.delete("/alerts/rules/{rule_id}", status_code=204)
def delete_alert_rule(
rule_id: int,
_: User = Depends(require_role("admin")),
db: Session = Depends(get_db),
) -> None:
rule = db.get(AlertRule, rule_id)
if rule is None:
raise HTTPException(status_code=404, detail="Alert rule not found")
db.delete(rule)
db.commit()
@router.get("/incidents", response_model=list[IncidentRead])
def list_incidents(_: User = Depends(get_current_user), db: Session = Depends(get_db)) -> list[Incident]:
return list(db.scalars(select(Incident).order_by(Incident.opened_at.desc())).all())
@router.get("/incidents/{incident_id}", response_model=IncidentRead)
def get_incident(incident_id: int, _: User = Depends(get_current_user), db: Session = Depends(get_db)) -> Incident:
incident = db.get(Incident, incident_id)
if incident is None:
raise HTTPException(status_code=404, detail="Incident not found")
return incident
@router.post("/incidents/{incident_id}/acknowledge", response_model=IncidentRead)
def acknowledge_incident(
incident_id: int,
_: User = Depends(require_role("operator")),
db: Session = Depends(get_db),
) -> Incident:
incident = db.get(Incident, incident_id)
if incident is None:
raise HTTPException(status_code=404, detail="Incident not found")
incident.acknowledged_at = datetime.now(UTC)
db.commit()
db.refresh(incident)
return incident
@router.post("/incidents/{incident_id}/silence", response_model=IncidentRead)
def silence_incident(
incident_id: int,
minutes: int = 60,
_: User = Depends(require_role("operator")),
db: Session = Depends(get_db),
) -> Incident:
incident = db.get(Incident, incident_id)
if incident is None:
raise HTTPException(status_code=404, detail="Incident not found")
incident.silenced_until = datetime.now(UTC) + timedelta(minutes=minutes)
db.commit()
db.refresh(incident)
return incident