fix: 补充克隆音色权限校验 + 测试 user_id mock
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 28s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 19s
AI Code Review / AI Code Review (pull_request) Successful in 1m44s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m46s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m47s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m37s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m40s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 3m11s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m48s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 6m20s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 8m22s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 6m45s
CI/CD Pipeline / CI Gate (pull_request) Successful in 14s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 1m1s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m6s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 28s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 19s
AI Code Review / AI Code Review (pull_request) Successful in 1m44s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m46s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m47s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m37s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m40s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 3m11s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m48s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 6m20s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 8m22s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 6m45s
CI/CD Pipeline / CI Gate (pull_request) Successful in 14s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 1m1s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m6s
AI Code Review 指出越权风险:未校验 VoiceCloneProfile 归属。 新增 profile.user_id != authenticated_user.user.id → 403。 补充 12 个测试全部通过。
This commit is contained in:
@@ -392,7 +392,12 @@ def preview_tts(
|
||||
actual_voice_id = request.voice_id
|
||||
profile = voice_clone_repo.get(request.voice_id)
|
||||
if profile is not None:
|
||||
# 命中克隆音色 profile
|
||||
# 命中克隆音色 profile — 校验归属权限
|
||||
if profile.user_id != authenticated_user.user.id:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="无权访问该音色",
|
||||
)
|
||||
if not profile.voice_id:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
|
||||
@@ -309,6 +309,7 @@ class TestTTSPreviewEndpoint:
|
||||
|
||||
# Mock voice clone profile with voice_id
|
||||
mock_profile = MagicMock()
|
||||
mock_profile.user_id = "user-1"
|
||||
mock_profile.voice_id = "cosyvoice_actual_voice_123"
|
||||
mock_clone_repo = MagicMock()
|
||||
mock_clone_repo.get.return_value = mock_profile
|
||||
@@ -351,6 +352,7 @@ class TestTTSPreviewEndpoint:
|
||||
|
||||
# Mock voice clone profile with empty voice_id (clone not finished)
|
||||
mock_profile = MagicMock()
|
||||
mock_profile.user_id = "user-1"
|
||||
mock_profile.voice_id = ""
|
||||
mock_clone_repo = MagicMock()
|
||||
mock_clone_repo.get.return_value = mock_profile
|
||||
@@ -405,3 +407,35 @@ class TestTTSPreviewEndpoint:
|
||||
voice_id="longxiaoxia_v3",
|
||||
speed=1.0,
|
||||
)
|
||||
|
||||
def test_preview_clone_voice_wrong_user_returns_403(self):
|
||||
"""Accessing another user's clone profile returns 403."""
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
from app.api.routes.tts import router
|
||||
|
||||
app.include_router(router, prefix="/tts")
|
||||
|
||||
from app.auth import get_current_user
|
||||
from app.dependencies import get_voice_clone_profile_repository
|
||||
|
||||
fake_user = MagicMock()
|
||||
fake_user.user.id = "user-1"
|
||||
app.dependency_overrides[get_current_user] = lambda: fake_user
|
||||
|
||||
# Mock profile belonging to a different user
|
||||
mock_profile = MagicMock()
|
||||
mock_profile.user_id = "user-2"
|
||||
mock_profile.voice_id = "cosyvoice_voice_xyz"
|
||||
mock_clone_repo = MagicMock()
|
||||
mock_clone_repo.get.return_value = mock_profile
|
||||
app.dependency_overrides[get_voice_clone_profile_repository] = lambda: mock_clone_repo
|
||||
|
||||
client = self._make_client(app)
|
||||
resp = client.post(
|
||||
"/tts/preview",
|
||||
json={"text": "越权测试", "voice_id": "other-user-profile-uuid"},
|
||||
)
|
||||
assert resp.status_code == 403
|
||||
assert "无权访问该音色" in resp.json()["detail"]
|
||||
|
||||
Reference in New Issue
Block a user