| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- """
- Superadmin monitoring endpoints for host metrics and alerts.
- """
- from datetime import datetime, timedelta, timezone
- from fastapi import APIRouter, Depends, Query
- from sqlalchemy import select
- from sqlalchemy.ext.asyncio import AsyncSession
- from app.api.deps import get_current_superadmin, get_db
- from app.models.alert import Alert
- from app.models.host_metrics import HostMetrics
- from app.models.security_event import SecurityEvent
- from app.services.alert_service import alert_service
- router = APIRouter()
- @router.get("/host-metrics/recent")
- async def get_recent_host_metrics(
- limit: int = Query(default=60, le=1000),
- db: AsyncSession = Depends(get_db),
- _current_user=Depends(get_current_superadmin),
- ):
- """Get recent host metrics for dashboard charts (default: last 60 data points)."""
- result = await db.execute(
- select(HostMetrics)
- .order_by(HostMetrics.timestamp.desc())
- .limit(limit)
- )
- metrics = list(result.scalars().all())
- # Return in chronological order
- return [
- {
- "timestamp": m.timestamp.isoformat(),
- "cpu_percent": m.cpu_percent,
- "cpu_count": m.cpu_count,
- "memory_total": m.memory_total,
- "memory_used": m.memory_used,
- "memory_percent": m.memory_percent,
- "load_1": m.load_1,
- "load_5": m.load_5,
- "load_15": m.load_15,
- "disk_read_bytes": m.disk_read_bytes,
- "disk_write_bytes": m.disk_write_bytes,
- "disk_usage_percent": m.disk_usage_percent,
- "net_sent_bytes": m.net_sent_bytes,
- "net_recv_bytes": m.net_recv_bytes,
- }
- for m in reversed(metrics)
- ]
- @router.get("/host-metrics/history")
- async def get_host_metrics_history(
- start_date: datetime = Query(...),
- end_date: datetime = Query(...),
- db: AsyncSession = Depends(get_db),
- _current_user=Depends(get_current_superadmin),
- ):
- """Get historical host metrics for specified date range."""
- result = await db.execute(
- select(HostMetrics)
- .where(HostMetrics.timestamp >= start_date)
- .where(HostMetrics.timestamp <= end_date)
- .order_by(HostMetrics.timestamp.asc())
- )
- metrics = list(result.scalars().all())
- return [
- {
- "timestamp": m.timestamp.isoformat(),
- "cpu_percent": m.cpu_percent,
- "cpu_count": m.cpu_count,
- "memory_total": m.memory_total,
- "memory_used": m.memory_used,
- "memory_percent": m.memory_percent,
- "load_1": m.load_1,
- "load_5": m.load_5,
- "load_15": m.load_15,
- "disk_read_bytes": m.disk_read_bytes,
- "disk_write_bytes": m.disk_write_bytes,
- "disk_usage_percent": m.disk_usage_percent,
- "net_sent_bytes": m.net_sent_bytes,
- "net_recv_bytes": m.net_recv_bytes,
- }
- for m in metrics
- ]
- @router.get("/alerts")
- async def get_alerts(
- dismissed: bool = Query(default=False),
- db: AsyncSession = Depends(get_db),
- _current_user=Depends(get_current_superadmin),
- ):
- """Get alerts (by default only active/non-dismissed alerts)."""
- query = select(Alert).order_by(Alert.timestamp.desc())
- if not dismissed:
- query = query.where(Alert.dismissed == False)
- result = await db.execute(query)
- alerts = list(result.scalars().all())
- return [
- {
- "id": a.id,
- "timestamp": a.timestamp.isoformat(),
- "alert_type": a.alert_type,
- "severity": a.severity,
- "title": a.title,
- "message": a.message,
- "alert_metadata": a.alert_metadata,
- "acknowledged": a.acknowledged,
- "acknowledged_at": a.acknowledged_at.isoformat() if a.acknowledged_at else None,
- "acknowledged_by": a.acknowledged_by,
- "dismissed": a.dismissed,
- "dismissed_at": a.dismissed_at.isoformat() if a.dismissed_at else None,
- "sent_dashboard": a.sent_dashboard,
- "sent_telegram": a.sent_telegram,
- "sent_email": a.sent_email,
- }
- for a in alerts
- ]
- @router.post("/alerts/{alert_id}/acknowledge")
- async def acknowledge_alert(
- alert_id: int,
- db: AsyncSession = Depends(get_db),
- current_user=Depends(get_current_superadmin),
- ):
- """Mark alert as acknowledged."""
- await alert_service.acknowledge_alert(db, alert_id, current_user.id)
- return {"status": "ok"}
- @router.post("/alerts/{alert_id}/dismiss")
- async def dismiss_alert(
- alert_id: int,
- db: AsyncSession = Depends(get_db),
- _current_user=Depends(get_current_superadmin),
- ):
- """Mark alert as dismissed (hide from dashboard)."""
- await alert_service.dismiss_alert(db, alert_id)
- return {"status": "ok"}
- @router.get("/security-events")
- async def get_security_events(
- resolved: bool = Query(default=False),
- limit: int = Query(default=100, le=1000),
- db: AsyncSession = Depends(get_db),
- _current_user=Depends(get_current_superadmin),
- ):
- """Get security events (by default only unresolved events)."""
- query = select(SecurityEvent).order_by(SecurityEvent.timestamp.desc()).limit(limit)
- if not resolved:
- query = query.where(SecurityEvent.resolved == False)
- result = await db.execute(query)
- events = list(result.scalars().all())
- return [
- {
- "id": e.id,
- "timestamp": e.timestamp.isoformat(),
- "event_type": e.event_type,
- "severity": e.severity,
- "ip_address": e.ip_address,
- "user_agent": e.user_agent,
- "endpoint": e.endpoint,
- "description": e.description,
- "event_metadata": e.event_metadata,
- "resolved": e.resolved,
- "resolved_at": e.resolved_at.isoformat() if e.resolved_at else None,
- "resolved_by": e.resolved_by,
- }
- for e in events
- ]
- @router.post("/security-events/{event_id}/resolve")
- async def resolve_security_event(
- event_id: int,
- db: AsyncSession = Depends(get_db),
- current_user=Depends(get_current_superadmin),
- ):
- """Mark security event as resolved."""
- result = await db.execute(
- select(SecurityEvent).where(SecurityEvent.id == event_id)
- )
- event = result.scalar_one_or_none()
- if event:
- event.resolved = True
- event.resolved_at = datetime.now(timezone.utc)
- event.resolved_by = current_user.id
- await db.commit()
- return {"status": "ok"}
|