107 lines
3.5 KiB
Python
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
|