from typing import Optional, List from fastapi import APIRouter, Depends, Query from sqlalchemy.orm import Session from pydantic import BaseModel from app.core.database import get_db from app.models.user import User from app.schemas.common import ResponseModel, ListResponse from app.services import api_asset_service from app.api.deps import get_current_user router = APIRouter() class APIAssetCreate(BaseModel): name: str base_url: str swagger_url: Optional[str] = None auth_type: Optional[str] = "none" headers: Optional[dict] = None description: Optional[str] = None class APIAssetUpdate(BaseModel): name: Optional[str] = None base_url: Optional[str] = None swagger_url: Optional[str] = None auth_type: Optional[str] = None headers: Optional[dict] = None description: Optional[str] = None @router.post("") def create_asset( body: APIAssetCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): asset = api_asset_service.create_asset(db, body.dict(), current_user.id) return ResponseModel(data={"id": asset.id}) @router.get("") def list_assets( page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=500), db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): from app.models.api_asset import APIAsset query = db.query(APIAsset) total = query.count() items = query.order_by(APIAsset.created_at.desc()).offset((page - 1) * page_size).limit(page_size).all() return ListResponse( data=[{ "id": a.id, "name": a.name, "base_url": a.base_url, "swagger_url": a.swagger_url, "auth_type": a.auth_type, "scan_status": a.scan_status, "total_endpoints": a.total_endpoints, "sensitive_endpoints": a.sensitive_endpoints, "created_at": a.created_at.isoformat() if a.created_at else None, } for a in items], total=total, page=page, page_size=page_size, ) @router.put("/{asset_id}") def update_asset( asset_id: int, body: APIAssetUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): asset = api_asset_service.update_asset(db, asset_id, body.dict(exclude_unset=True)) if not asset: from fastapi import HTTPException, status raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="资产不存在") return ResponseModel(data={"id": asset.id}) @router.delete("/{asset_id}") def delete_asset( asset_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): ok = api_asset_service.delete_asset(db, asset_id) if not ok: from fastapi import HTTPException, status raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="资产不存在") return ResponseModel() @router.post("/{asset_id}/scan") def scan_asset( asset_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): result = api_asset_service.scan_swagger(db, asset_id) return ResponseModel(data=result) @router.get("/{asset_id}/endpoints") def list_endpoints( asset_id: int, risk_level: Optional[str] = Query(None), page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=500), db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): from app.models.api_asset import APIEndpoint query = db.query(APIEndpoint).filter(APIEndpoint.asset_id == asset_id) if risk_level: query = query.filter(APIEndpoint.risk_level == risk_level) total = query.count() items = query.order_by(APIEndpoint.id.asc()).offset((page - 1) * page_size).limit(page_size).all() return ListResponse( data=[{ "id": e.id, "method": e.method, "path": e.path, "summary": e.summary, "tags": e.tags, "parameters": e.parameters, "sensitive_fields": e.sensitive_fields, "risk_level": e.risk_level, "is_active": e.is_active, } for e in items], total=total, page=page, page_size=page_size, )