feat: Phase 4 多租户隔离 + 四阶段升级测试 + CSS 统一化
Phase 4: org_id 注入 JWT/API 过滤/组织管理 CRUD/前端组织列 测试: tests/test_phase_upgrades.py 97项全覆盖 CSS: theme-modern.css 共享 mobile-card-list/status-dot/search-bar 等模式 修复: initial_data.py LLM配置 NOT NULL 约束, TopicResponse 含 org_id
This commit is contained in:
@@ -13,7 +13,7 @@ from ..core.generator import run_creator
|
||||
from ..core.optimizer import run_optimizer
|
||||
from ..core.sync import sync_all_topics
|
||||
from ..core.scheduler import scheduler
|
||||
from .auth import get_current_user
|
||||
from .auth import get_current_user, org_filter
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[4]
|
||||
if os.getenv('PROJECT_ROOT'):
|
||||
@@ -23,9 +23,9 @@ LOGS_DIR = PROJECT_ROOT / "automation" / "logs"
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/api/system", tags=["system"])
|
||||
|
||||
def _aggregate_status_counts(db: Session):
|
||||
def _aggregate_status_counts(q):
|
||||
"""聚合状态计数,兼容中英文状态值"""
|
||||
raw = db.query(Topic.status, func.count()).group_by(Topic.status).all()
|
||||
raw = q.with_entities(Topic.status, func.count()).group_by(Topic.status).all()
|
||||
mapping = {
|
||||
'pending': ['pending', '待处理'],
|
||||
'review': ['review', '待审查'],
|
||||
@@ -43,7 +43,7 @@ def _aggregate_status_counts(db: Session):
|
||||
@router.get("/status")
|
||||
def get_status(db: Session = Depends(get_db)):
|
||||
total = db.query(Topic).count()
|
||||
counts = _aggregate_status_counts(db)
|
||||
counts = _aggregate_status_counts(db.query(Topic))
|
||||
today = date.today()
|
||||
today_count = db.query(Topic).filter(func.date(Topic.created_at) == today).count()
|
||||
return {
|
||||
@@ -58,7 +58,7 @@ def get_status(db: Session = Depends(get_db)):
|
||||
}
|
||||
|
||||
@router.post("/generate/run", dependencies=[Depends(get_current_user)])
|
||||
def trigger_generation(topic_id: str = Body(None, embed=True), db: Session = Depends(get_db)):
|
||||
def trigger_generation(topic_id: str = Body(None, embed=True), db: Session = Depends(get_db), current_user=Depends(get_current_user)):
|
||||
logger.info(f"Received topic_id={topic_id}")
|
||||
try:
|
||||
result = run_creator(topic_id)
|
||||
@@ -70,7 +70,7 @@ def trigger_generation(topic_id: str = Body(None, embed=True), db: Session = Dep
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@router.post("/review/run", dependencies=[Depends(get_current_user)])
|
||||
def trigger_review(topic_ids: List[str] = Body(None, embed=True), db: Session = Depends(get_db)):
|
||||
def trigger_review(topic_ids: List[str] = Body(None, embed=True), db: Session = Depends(get_db), current_user=Depends(get_current_user)):
|
||||
try:
|
||||
result = run_optimizer(topic_ids)
|
||||
if not result["ok"]:
|
||||
@@ -86,7 +86,11 @@ def trigger_review(topic_ids: List[str] = Body(None, embed=True), db: Session =
|
||||
if topic_ids:
|
||||
updated = 0
|
||||
for tid in topic_ids:
|
||||
topic = db.query(Topic).filter(Topic.id == tid).first()
|
||||
q = db.query(Topic).filter(Topic.id == tid)
|
||||
of = org_filter(current_user, Topic)
|
||||
if of is not True:
|
||||
q = q.filter(of)
|
||||
topic = q.first()
|
||||
if topic and topic.status in ('review', '待审查'):
|
||||
topic.status = 'ready'
|
||||
if not topic.generated_at:
|
||||
@@ -109,9 +113,13 @@ def get_logs(log_date: str, log_type: str = "creator"):
|
||||
return {"log_date": log_date, "log_type": log_type, "content": lines}
|
||||
|
||||
@router.get("/pipeline/status", dependencies=[Depends(get_current_user)])
|
||||
def get_pipeline_status(db: Session = Depends(get_db)):
|
||||
total = db.query(Topic).count()
|
||||
counts = _aggregate_status_counts(db)
|
||||
def get_pipeline_status(db: Session = Depends(get_db), current_user=Depends(get_current_user)):
|
||||
topic_base = db.query(Topic)
|
||||
of = org_filter(current_user, Topic)
|
||||
if of is not True:
|
||||
topic_base = topic_base.filter(of)
|
||||
total = topic_base.count()
|
||||
counts = _aggregate_status_counts(topic_base)
|
||||
log_files = {
|
||||
"collector": LOGS_DIR / f"collector_{date.today().isoformat()}.log",
|
||||
"creator": LOGS_DIR / f"creator_{date.today().isoformat()}.log",
|
||||
@@ -135,9 +143,13 @@ def run_sync():
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@router.get("/automation/topics")
|
||||
def list_automation_topics(db: Session = Depends(get_db)):
|
||||
def list_automation_topics(db: Session = Depends(get_db), current_user=Depends(get_current_user)):
|
||||
try:
|
||||
topics = db.query(Topic).order_by(Topic.created_at.desc()).limit(100).all()
|
||||
topic_base = db.query(Topic)
|
||||
of = org_filter(current_user, Topic)
|
||||
if of is not True:
|
||||
topic_base = topic_base.filter(of)
|
||||
topics = topic_base.order_by(Topic.created_at.desc()).limit(100).all()
|
||||
result = []
|
||||
for t in topics:
|
||||
result.append({
|
||||
|
||||
Reference in New Issue
Block a user