from pathlib import Path from fastapi import APIRouter, Depends, Header, HTTPException, Request from fastapi.responses import FileResponse from app.core.security import admin_auth, token_digest from app.repositories import crash_report_repository router = APIRouter(tags=["admin-crash-report"]) @router.get("/admin/crash-report/list") def admin_crash_report_list(limit: int = 300, auth=Depends(admin_auth)): limit = max(1, min(limit, 1000)) return {"list": crash_report_repository.list_crash_reports(limit)} @router.get("/admin/crash-report/file/{report_id}/{file_name}") def admin_crash_report_file( report_id: str, file_name: str, request: Request, X_Admin_Token: str = Header(""), auth=Depends(admin_auth), ): allowed = { "metadata": "metadata.json", "metadata.json": "metadata.json", "minidump": "crash.dmp", "crash.dmp": "crash.dmp", "attachments": "attachments.zip", "attachments.zip": "attachments.zip", "server": "server.json", "server.json": "server.json", } stored_name = allowed.get(file_name) if not stored_name: raise HTTPException(status_code=404, detail="崩溃报告文件不存在") row = crash_report_repository.get_crash_report(report_id) if not row: raise HTTPException(status_code=404, detail="崩溃报告不存在") target = Path(row["storage_path"]) / stored_name if not target.is_file(): raise HTTPException(status_code=404, detail="崩溃报告文件不存在") crash_report_repository.log_file_access( report_id, stored_name, token_digest(X_Admin_Token)[:16], request.client.host if request.client else "", request.headers.get("user-agent", "")[:300], ) return FileResponse(target, media_type="application/octet-stream", filename=stored_name)