You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.3 KiB

"""
扫描管理API路由
"""
from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks
from sqlalchemy.orm import Session
from typing import List
from app.database import get_db
from app.models.scan import Scan, ScanStatus, ScanType
from app.models.project import Project
from app.schemas.scan import ScanCreate, ScanResponse, ScanStatusResponse
from app.services.scan_service import ScanService
router = APIRouter()
@router.get("/", response_model=List[ScanResponse])
async def get_scans(
project_id: int = None,
skip: int = 0,
limit: int = 100,
db: Session = Depends(get_db)
):
"""获取扫描历史"""
query = db.query(Scan)
if project_id:
query = query.filter(Scan.project_id == project_id)
scans = query.order_by(Scan.created_at.desc()).offset(skip).limit(limit).all()
return scans
@router.post("/", response_model=ScanResponse, status_code=status.HTTP_201_CREATED)
async def create_scan(
scan_data: ScanCreate,
background_tasks: BackgroundTasks,
db: Session = Depends(get_db)
):
"""创建并启动扫描任务"""
# 验证项目存在
project = db.query(Project).filter(Project.id == scan_data.project_id).first()
if not project:
raise HTTPException(status_code=404, detail="项目不存在")
# 创建扫描记录
scan = Scan(
project_id=scan_data.project_id,
scan_type=scan_data.scan_type,
scan_config=scan_data.scan_config,
status=ScanStatus.PENDING
)
db.add(scan)
db.commit()
db.refresh(scan)
# 启动后台扫描任务
background_tasks.add_task(ScanService.run_scan, scan.id)
return scan
@router.get("/{scan_id}", response_model=ScanResponse)
async def get_scan(
scan_id: int,
db: Session = Depends(get_db)
):
"""获取扫描详情"""
scan = db.query(Scan).filter(Scan.id == scan_id).first()
if not scan:
raise HTTPException(status_code=404, detail="扫描任务不存在")
return scan
@router.get("/{scan_id}/status", response_model=ScanStatusResponse)
async def get_scan_status(
scan_id: int,
db: Session = Depends(get_db)
):
"""获取扫描状态"""
scan = db.query(Scan).filter(Scan.id == scan_id).first()
if not scan:
raise HTTPException(status_code=404, detail="扫描任务不存在")
return {
"scan_id": scan.id,
"status": scan.status.value,
"progress": {
"total_files": scan.total_files,
"scanned_files": scan.scanned_files,
"percentage": (scan.scanned_files / scan.total_files * 100) if scan.total_files > 0 else 0
},
"started_at": scan.started_at,
"completed_at": scan.completed_at,
"error_message": scan.error_message
}
@router.post("/{scan_id}/cancel")
async def cancel_scan(
scan_id: int,
db: Session = Depends(get_db)
):
"""取消扫描任务"""
scan = db.query(Scan).filter(Scan.id == scan_id).first()
if not scan:
raise HTTPException(status_code=404, detail="扫描任务不存在")
if scan.status in [ScanStatus.COMPLETED, ScanStatus.FAILED, ScanStatus.CANCELLED]:
raise HTTPException(status_code=400, detail="扫描任务已完成或已取消")
scan.status = ScanStatus.CANCELLED
db.commit()
return {"message": "扫描任务已取消"}