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
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": "扫描任务已取消"}
|