Bruno Charest 817f8b4ee7
Some checks failed
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
feat: Implement Homelab Automation API v2, introducing a new dashboard, comprehensive backend models, and API routes.
2026-03-06 09:31:08 -05:00

170 lines
4.6 KiB
Python

"""
Routes API pour les alertes.
"""
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.dependencies import get_db, verify_api_key
from app.crud.alert import AlertRepository
from app.services import ws_manager
router = APIRouter()
class AlertCreate(BaseModel):
category: str = "general"
level: Optional[str] = "info"
title: Optional[str] = None
message: str
source: Optional[str] = None
@router.post("")
async def create_alert(
alert_data: AlertCreate,
api_key_valid: bool = Depends(verify_api_key),
db_session: AsyncSession = Depends(get_db)
):
"""Crée une nouvelle alerte."""
try:
repo = AlertRepository(db_session)
alert = await repo.create(
category=alert_data.category,
level=alert_data.level,
title=alert_data.title,
message=alert_data.message,
source=alert_data.source,
)
await db_session.refresh(alert)
# Access attributes before commit to avoid MissingGreenlet on async lazy loading
alert_dict = {
"id": alert.id,
"title": alert.title,
"message": alert.message,
"level": alert.level,
"category": alert.category,
"created_at": alert.created_at,
}
await db_session.commit()
await ws_manager.broadcast({
"type": "alert_created",
"data": {
"id": alert_dict["id"],
"title": alert_dict["title"],
"message": alert_dict["message"],
"level": alert_dict["level"],
}
})
return alert_dict
except Exception as e:
import traceback
traceback.print_exc()
raise HTTPException(status_code=500, detail=str(e))
@router.get("")
async def get_alerts(
limit: int = 50,
offset: int = 0,
unread_only: bool = False,
api_key_valid: bool = Depends(verify_api_key),
db_session: AsyncSession = Depends(get_db)
):
"""Récupère les alertes avec pagination."""
repo = AlertRepository(db_session)
alerts = await repo.list(limit=limit, offset=offset, unread_only=unread_only)
return {
"alerts": [
{
"id": a.id,
"title": a.title,
"message": a.message,
"level": a.level,
"source": a.source,
"category": a.category,
"read": a.read_at is not None,
"read_at": a.read_at,
"created_at": a.created_at,
}
for a in alerts
],
"count": len(alerts)
}
@router.get("/unread-count")
async def get_unread_count(
api_key_valid: bool = Depends(verify_api_key),
db_session: AsyncSession = Depends(get_db)
):
"""Récupère le nombre d'alertes non lues."""
repo = AlertRepository(db_session)
count = await repo.count_unread()
return {"unread": count}
@router.post("/{alert_id}/read")
async def mark_as_read(
alert_id: str,
api_key_valid: bool = Depends(verify_api_key),
db_session: AsyncSession = Depends(get_db)
):
"""Marque une alerte comme lue."""
repo = AlertRepository(db_session)
alert = await repo.get(alert_id)
if not alert:
raise HTTPException(status_code=404, detail="Alerte non trouvée")
await repo.mark_as_read(alert_id)
await db_session.commit()
return {"message": "Alerte marquée comme lue", "id": alert_id}
@router.post("/mark-all-read")
async def mark_all_as_read(
api_key_valid: bool = Depends(verify_api_key),
db_session: AsyncSession = Depends(get_db)
):
"""Marque toutes les alertes comme lues."""
repo = AlertRepository(db_session)
count = await repo.mark_all_as_read()
await db_session.commit()
await ws_manager.broadcast({
"type": "alerts_cleared",
"data": {"count": count}
})
return {"message": f"{count} alerte(s) marquée(s) comme lue(s)"}
@router.delete("/{alert_id}")
async def delete_alert(
alert_id: str,
api_key_valid: bool = Depends(verify_api_key),
db_session: AsyncSession = Depends(get_db)
):
"""Supprime une alerte."""
repo = AlertRepository(db_session)
alert = await repo.get(alert_id)
if not alert:
raise HTTPException(status_code=404, detail="Alerte non trouvée")
await repo.delete(alert_id)
await db_session.commit()
return {"message": "Alerte supprimée", "id": alert_id}