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:
Yuzhiran Dev
2026-05-17 06:56:53 +08:00
parent 301dc3e438
commit 9c37c9a574
45 changed files with 3707 additions and 1366 deletions
+12 -3
View File
@@ -6,7 +6,7 @@ from typing import List, Optional
from ..database import get_db
from ..models import ContentTask, Topic
from ..schemas import ContentTaskCreate, ContentTaskResponse
from .auth import get_current_user
from .auth import get_current_user, org_filter
router = APIRouter(prefix="/api/tasks", tags=["tasks"])
@@ -20,7 +20,10 @@ def list_tasks(
db: Session = Depends(get_db),
current_user=Depends(get_current_user)
):
query = db.query(ContentTask)
query = db.query(ContentTask).join(Topic, ContentTask.topic_id == Topic.id, isouter=True)
of = org_filter(current_user, Topic)
if of is not True:
query = query.filter((ContentTask.topic_id.is_(None)) | (Topic.org_id == current_user.org_id))
if status:
query = query.filter(ContentTask.status == status)
if topic_id:
@@ -35,7 +38,11 @@ def get_active_tasks(
db: Session = Depends(get_db),
current_user=Depends(get_current_user)
):
return db.query(ContentTask).filter(
q = db.query(ContentTask).join(Topic, ContentTask.topic_id == Topic.id, isouter=True)
of = org_filter(current_user, Topic)
if of is not True:
q = q.filter((ContentTask.topic_id.is_(None)) | (Topic.org_id == current_user.org_id))
return q.filter(
ContentTask.status == "running"
).order_by(ContentTask.started_at.desc()).all()
@@ -50,6 +57,8 @@ def create_task(
topic = db.query(Topic).filter(Topic.id == data.topic_id).first()
if not topic:
raise HTTPException(status_code=404, detail="选题不存在")
if current_user.role != "admin" and topic.org_id != current_user.org_id:
raise HTTPException(status_code=404, detail="选题不存在")
task_id = f"task_{uuid.uuid4().hex[:16]}"