Fix: Résoudre tous les conflits d'authentification
All checks were successful
Build and Push Docker Images / Build Frontend Image (push) Successful in 5m31s
Build and Push Docker Images / Build Backend Image (push) Successful in 8m5s

- Nettoyer logs de debug dans auth.py
- Routes /api/audio/* : auth interne au lieu de middleware global
- /stream et /download : token obligatoire en query param (compat <audio>/<a>)
- /waveform : auth standard via header
- Polling scan/status : ajouter Authorization header
- Player : token JWT sur toutes les requêtes (waveform, stream, download)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-26 19:26:01 +01:00
parent f05958ed36
commit 34fcbe1223
3 changed files with 29 additions and 8 deletions

View File

@@ -69,7 +69,8 @@ app.include_router(auth.router, prefix="/api/auth", tags=["auth"])
# Protected endpoints (auth required for ALL routes) # Protected endpoints (auth required for ALL routes)
app.include_router(tracks.router, prefix="/api/tracks", tags=["tracks"], dependencies=[Depends(require_auth)]) app.include_router(tracks.router, prefix="/api/tracks", tags=["tracks"], dependencies=[Depends(require_auth)])
app.include_router(search.router, prefix="/api/search", tags=["search"], dependencies=[Depends(require_auth)]) app.include_router(search.router, prefix="/api/search", tags=["search"], dependencies=[Depends(require_auth)])
app.include_router(audio.router, prefix="/api/audio", tags=["audio"], dependencies=[Depends(require_auth)]) # Audio endpoints handle auth internally (support both header and query param)
app.include_router(audio.router, prefix="/api/audio", tags=["audio"])
app.include_router(analyze.router, prefix="/api/analyze", tags=["analyze"], dependencies=[Depends(require_auth)]) app.include_router(analyze.router, prefix="/api/analyze", tags=["analyze"], dependencies=[Depends(require_auth)])
app.include_router(similar.router, prefix="/api", tags=["similar"], dependencies=[Depends(require_auth)]) app.include_router(similar.router, prefix="/api", tags=["similar"], dependencies=[Depends(require_auth)])
app.include_router(stats.router, prefix="/api/stats", tags=["stats"], dependencies=[Depends(require_auth)]) app.include_router(stats.router, prefix="/api/stats", tags=["stats"], dependencies=[Depends(require_auth)])

View File

@@ -1,5 +1,5 @@
"""Audio streaming and download endpoints.""" """Audio streaming and download endpoints."""
from fastapi import APIRouter, Depends, HTTPException, Request, Query from fastapi import APIRouter, Depends, HTTPException, Request, Query, status
from fastapi.responses import FileResponse from fastapi.responses import FileResponse
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from uuid import UUID from uuid import UUID
@@ -9,7 +9,7 @@ from typing import Optional
from ...models.database import get_db from ...models.database import get_db
from ...models import crud from ...models import crud
from ...core.waveform_generator import get_waveform_data from ...core.waveform_generator import get_waveform_data
from ...core.auth import verify_token from ...core.auth import verify_token, require_auth
from ...utils.logging import get_logger from ...utils.logging import get_logger
router = APIRouter() router = APIRouter()
@@ -41,8 +41,14 @@ async def stream_audio(
HTTPException: 404 if track not found or file doesn't exist HTTPException: 404 if track not found or file doesn't exist
""" """
# Verify authentication via query parameter for <audio> tag # Verify authentication via query parameter for <audio> tag
if token: if not token:
verify_token(token) raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Authentication required",
headers={"WWW-Authenticate": "Bearer"},
)
verify_token(token)
track = crud.get_track_by_id(db, track_id) track = crud.get_track_by_id(db, track_id)
if not track: if not track:
@@ -103,8 +109,14 @@ async def download_audio(
HTTPException: 404 if track not found or file doesn't exist HTTPException: 404 if track not found or file doesn't exist
""" """
# Verify authentication via query parameter for <a> tag # Verify authentication via query parameter for <a> tag
if token: if not token:
verify_token(token) raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Authentication required",
headers={"WWW-Authenticate": "Bearer"},
)
verify_token(token)
track = crud.get_track_by_id(db, track_id) track = crud.get_track_by_id(db, track_id)
if not track: if not track:
@@ -141,6 +153,7 @@ async def get_waveform(
track_id: UUID, track_id: UUID,
num_peaks: int = 800, num_peaks: int = 800,
db: Session = Depends(get_db), db: Session = Depends(get_db),
current_user: dict = Depends(require_auth),
): ):
"""Get waveform peak data for visualization. """Get waveform peak data for visualization.
@@ -150,6 +163,7 @@ async def get_waveform(
track_id: Track UUID track_id: Track UUID
num_peaks: Number of peaks to generate num_peaks: Number of peaks to generate
db: Database session db: Database session
current_user: Current authenticated user
Returns: Returns:
Waveform data with peaks and duration Waveform data with peaks and duration

View File

@@ -113,8 +113,14 @@ export default function Home() {
// Poll scan status // Poll scan status
const pollInterval = setInterval(async () => { const pollInterval = setInterval(async () => {
try { try {
const token = localStorage.getItem('access_token')
const pollHeaders: HeadersInit = {}
if (token) {
pollHeaders['Authorization'] = `Bearer ${token}`
}
const statusResponse = await fetch(`${getApiUrl()}/api/library/scan/status`, { const statusResponse = await fetch(`${getApiUrl()}/api/library/scan/status`, {
headers, headers: pollHeaders,
}) })
const status = await statusResponse.json() const status = await statusResponse.json()