1e1e5957e8
- Ips.vue: el-select 添加 width: 280px,修复网段下拉框过窄 - Ips.vue: query 参数 networkId → network_id(与 FastAPI snake_case 一致) - Scan.vue: el-select 用 network.id 代替整个 network 对象作为 value,修复切换网段不生效 - enhanced_scan_service.py: 替换失效的 scapy ARP 扫描为 arp-scan 命令;扫描结果自动创建缺失 IP 记录
183 lines
5.8 KiB
Python
183 lines
5.8 KiB
Python
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.orm import Session
|
|
from typing import Optional
|
|
|
|
from app.core.database import get_db
|
|
from app.core.security import get_current_user
|
|
from app.services.alert_service import AlertService
|
|
|
|
router = APIRouter(
|
|
prefix="/alerts",
|
|
tags=["告警管理"],
|
|
dependencies=[Depends(get_current_user)],
|
|
)
|
|
|
|
|
|
@router.get("", summary="获取告警列表")
|
|
def get_alerts(
|
|
status: Optional[str] = None,
|
|
severity: Optional[str] = None,
|
|
alert_type: Optional[str] = None,
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""获取告警列表"""
|
|
from app.models.alert import Alert
|
|
|
|
query = db.query(Alert)
|
|
|
|
if status:
|
|
query = query.filter(Alert.status == status)
|
|
if severity:
|
|
query = query.filter(Alert.severity == severity)
|
|
if alert_type:
|
|
query = query.filter(Alert.alert_type == alert_type)
|
|
|
|
total = query.count()
|
|
items = query.order_by(Alert.created_at.desc()).offset(skip).limit(limit).all()
|
|
|
|
return {"total": total, "items": items}
|
|
|
|
|
|
@router.get("/{alert_id}", summary="获取告警详情")
|
|
def get_alert(alert_id: int, db: Session = Depends(get_db)):
|
|
from app.models.alert import Alert
|
|
|
|
alert = db.query(Alert).filter(Alert.id == alert_id).first()
|
|
if not alert:
|
|
raise HTTPException(status_code=404, detail="告警不存在")
|
|
return alert
|
|
|
|
|
|
@router.post("/{alert_id}/acknowledge", summary="确认告警")
|
|
def acknowledge_alert(alert_id: int, acknowledged_by: str = "system", db: Session = Depends(get_db)):
|
|
"""确认告警"""
|
|
alert = AlertService.acknowledge_alert(db, alert_id, acknowledged_by)
|
|
if not alert:
|
|
raise HTTPException(status_code=404, detail="告警不存在")
|
|
return {"message": "告警已确认", "alert": alert}
|
|
|
|
|
|
@router.post("/{alert_id}/resolve", summary="解决告警")
|
|
def resolve_alert(alert_id: int, resolved_by: str = "system", notes: str = "", db: Session = Depends(get_db)):
|
|
"""标记告警为已解决"""
|
|
alert = AlertService.resolve_alert(db, alert_id, resolved_by, notes)
|
|
if not alert:
|
|
raise HTTPException(status_code=404, detail="告警不存在")
|
|
return {"message": "告警已解决", "alert": alert}
|
|
|
|
|
|
@router.post("/{alert_id}/ignore", summary="忽略告警")
|
|
def ignore_alert(alert_id: int, db: Session = Depends(get_db)):
|
|
"""忽略告警"""
|
|
alert = AlertService.ignore_alert(db, alert_id)
|
|
if not alert:
|
|
raise HTTPException(status_code=404, detail="告警不存在")
|
|
return {"message": "告警已忽略", "alert": alert}
|
|
|
|
|
|
@router.post("/detect/run", summary="运行所有检测")
|
|
def run_detection(db: Session = Depends(get_db)):
|
|
"""立即运行所有告警检测"""
|
|
results = AlertService.run_all_detections(db)
|
|
return {"message": "检测完成", "results": results}
|
|
|
|
|
|
@router.get("/statistics/summary", summary="告警统计摘要")
|
|
def get_alert_statistics(db: Session = Depends(get_db)):
|
|
"""获取告警统计信息"""
|
|
stats = AlertService.get_statistics(db)
|
|
return stats
|
|
|
|
|
|
# ========== MAC 白名单管理 ==========
|
|
|
|
@router.get("/whitelist/macs", summary="获取 MAC 白名单")
|
|
def get_mac_whitelist(
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""获取 MAC 地址白名单"""
|
|
total, items = AlertService.get_mac_whitelist(db, skip=skip, limit=limit)
|
|
return {"total": total, "items": items}
|
|
|
|
|
|
@router.post("/whitelist/macs", summary="添加 MAC 到白名单")
|
|
def add_mac_to_whitelist(
|
|
mac_address: str,
|
|
description: Optional[str] = None,
|
|
owner: Optional[str] = None,
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""添加 MAC 地址到白名单"""
|
|
whitelist_mac = AlertService.add_mac_to_whitelist(
|
|
db,
|
|
mac_address=mac_address,
|
|
description=description,
|
|
owner=owner
|
|
)
|
|
return {"message": "MAC 已添加到白名单", "item": whitelist_mac}
|
|
|
|
|
|
@router.delete("/whitelist/macs/{mac_id}", summary="从白名单移除 MAC")
|
|
def remove_mac_from_whitelist(mac_id: int, db: Session = Depends(get_db)):
|
|
"""从白名单移除 MAC 地址"""
|
|
success = AlertService.remove_mac_from_whitelist(db, mac_id)
|
|
if not success:
|
|
raise HTTPException(status_code=404, detail="MAC 不存在")
|
|
return {"message": "MAC 已从白名单移除"}
|
|
|
|
|
|
# ========== 单独检测接口 ==========
|
|
|
|
@router.post("/detect/ip-conflicts", summary="检测 IP 冲突")
|
|
def detect_ip_conflicts(db: Session = Depends(get_db)):
|
|
"""仅检测 IP 冲突"""
|
|
conflicts = AlertService.detect_ip_conflicts(db)
|
|
return {
|
|
"count": len(conflicts),
|
|
"conflicts": conflicts
|
|
}
|
|
|
|
|
|
@router.post("/detect/unauthorized", summary="检测未授权接入")
|
|
def detect_unauthorized_access(db: Session = Depends(get_db)):
|
|
"""仅检测未授权接入"""
|
|
unauthorized = AlertService.detect_unauthorized_access(db)
|
|
return {
|
|
"count": len(unauthorized),
|
|
"devices": unauthorized
|
|
}
|
|
|
|
|
|
@router.post("/detect/subnet-exhaustion", summary="检测网段耗尽")
|
|
def detect_subnet_exhaustion(db: Session = Depends(get_db)):
|
|
"""仅检测网段耗尽"""
|
|
exhaustion = AlertService.detect_subnet_exhaustion(db)
|
|
return {
|
|
"count": len(exhaustion),
|
|
"subnets": exhaustion
|
|
}
|
|
|
|
|
|
@router.post("/detect/new-devices", summary="检测新设备")
|
|
def detect_new_devices(db: Session = Depends(get_db)):
|
|
"""仅检测新发现的设备"""
|
|
new_devices = AlertService.detect_new_devices(db)
|
|
return {
|
|
"count": len(new_devices),
|
|
"devices": new_devices
|
|
}
|
|
|
|
|
|
@router.post("/detect/offline-devices", summary="检测离线设备")
|
|
def detect_offline_devices(db: Session = Depends(get_db)):
|
|
"""仅检测离线设备"""
|
|
offline_devices = AlertService.detect_device_offline(db)
|
|
return {
|
|
"count": len(offline_devices),
|
|
"devices": offline_devices
|
|
}
|