Files
yu-zhi-ran/platform/backend/app/api/optimizer_logs.py
T
Yuzhiran Dev d601a26850 fix: API route security fixes (path traversal, auth, bare except)
- articles.py: Path traversal sanitization
- optimizer_logs.py: Admin auth guard
- platform_config.py: Admin auth guard
- system.py: Path traversal whitelist
- topic_config.py: Admin auth guard
- topics.py: Minor fix

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-16 08:23:50 +08:00

78 lines
2.9 KiB
Python

import re
from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy.orm import Session
from pathlib import Path
import subprocess
from ..database import get_db
from ..models import User
from .auth import get_current_admin
router = APIRouter(prefix="/api", tags=["optimizer_logs"])
PROJECT_ROOT = Path(__file__).parent.parent.parent.parent.parent
@router.post("/optimizer/run")
async def run_optimizer(
request: Request,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_admin)
):
"""
触发合规优化器运行(管理员)
"""
try:
body = await request.json()
except Exception:
raise HTTPException(status_code=400, detail="Invalid JSON")
topic_id = body.get("topic_id")
if not topic_id:
raise HTTPException(status_code=400, detail="topic_id is required")
script_path = PROJECT_ROOT / "automation" / "scripts" / "compliance_optimizer.py"
if not script_path.exists():
raise HTTPException(status_code=500, detail="Optimizer script not found")
try:
result = subprocess.run(
["python", str(script_path), "--topic-id", topic_id],
capture_output=True,
text=True,
timeout=600,
cwd=PROJECT_ROOT
)
if result.returncode != 0:
raise HTTPException(status_code=500, detail=f"Optimizer failed: {result.stderr}")
return {"ok": True, "message": "Optimization completed", "output": result.stdout}
except subprocess.TimeoutExpired:
raise HTTPException(status_code=500, detail="Optimizer timed out")
@router.get("/logs")
def get_logs(
request: Request,
type: str = None, # creator, optimizer, collector
date: str = None, # YYYY-MM-DD
db: Session = Depends(get_db),
current_user: User = Depends(get_current_admin)
):
"""
读取系统日志文件内容(管理员)
"""
if not type or not date:
raise HTTPException(status_code=400, detail="type and date parameters are required")
_ALLOWED_LOG_TYPES = {"creator", "collector", "optimizer", "sources", "metrics", "trends", "rank_tracker"}
if type not in _ALLOWED_LOG_TYPES:
raise HTTPException(status_code=400, detail=f"Invalid log type: {type}")
if not re.match(r'^\d{4}-\d{2}-\d{2}$', date):
raise HTTPException(status_code=400, detail="Invalid date format (expected YYYY-MM-DD)")
logs_dir = PROJECT_ROOT / "automation" / "logs"
filename = f"{type}_{date}.log"
log_path = logs_dir / filename
if not log_path.exists():
# 日志文件不存在返回空内容
return {"type": type, "date": date, "content": ""}
try:
content = log_path.read_text(encoding="utf-8")
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to read log: {str(e)}")
return {"type": type, "date": date, "content": content}