Fix: API Key validation from database, Python 3.12 compatibility, persistent volumes
This commit is contained in:
@@ -19,11 +19,11 @@ services:
|
|||||||
- ADMIN_USER=${ADMIN_USER:-admin}
|
- ADMIN_USER=${ADMIN_USER:-admin}
|
||||||
- ADMIN_PASSWORD=${ADMIN_PASSWORD:--whisper12510-}
|
- ADMIN_PASSWORD=${ADMIN_PASSWORD:--whisper12510-}
|
||||||
- LOG_RETENTION_DAYS=${LOG_RETENTION_DAYS:-30}
|
- LOG_RETENTION_DAYS=${LOG_RETENTION_DAYS:-30}
|
||||||
- DATABASE_URL=sqlite:///app/data/whisper_api.db
|
- DATABASE_URL=sqlite:////app/data/whisper_api.db
|
||||||
volumes:
|
volumes:
|
||||||
- ./models:/app/models
|
- whisper_models:/app/models
|
||||||
- ./data:/app/data
|
- whisper_data:/app/data
|
||||||
- ./uploads:/app/uploads
|
- whisper_uploads:/app/uploads
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
reservations:
|
reservations:
|
||||||
@@ -37,3 +37,8 @@ services:
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 60s
|
start_period: 60s
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
whisper_models:
|
||||||
|
whisper_data:
|
||||||
|
whisper_uploads:
|
||||||
|
|||||||
@@ -3,18 +3,33 @@ FROM nvidia/cuda:12.1.0-runtime-ubuntu22.04
|
|||||||
# Prevent interactive prompts
|
# Prevent interactive prompts
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
# Install system dependencies
|
# Install system dependencies with Python 3.12 from deadsnakes PPA
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
python3.11 \
|
software-properties-common \
|
||||||
python3.11-pip \
|
pkg-config \
|
||||||
python3.11-venv \
|
&& add-apt-repository ppa:deadsnakes/ppa -y \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get install -y \
|
||||||
|
python3.12 \
|
||||||
|
python3.12-dev \
|
||||||
|
python3.12-venv \
|
||||||
ffmpeg \
|
ffmpeg \
|
||||||
|
libavformat-dev \
|
||||||
|
libavcodec-dev \
|
||||||
|
libavdevice-dev \
|
||||||
|
libavutil-dev \
|
||||||
|
libavfilter-dev \
|
||||||
|
libswscale-dev \
|
||||||
|
libswresample-dev \
|
||||||
curl \
|
curl \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Set Python 3.11 as default
|
# Install pip for Python 3.12
|
||||||
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.11 1
|
RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.12
|
||||||
RUN update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1
|
|
||||||
|
# Set Python 3.12 as default
|
||||||
|
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.12 1
|
||||||
|
RUN update-alternatives --install /usr/bin/pip pip /usr/local/bin/pip3 1
|
||||||
|
|
||||||
# Set working directory
|
# Set working directory
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
@@ -23,12 +38,19 @@ WORKDIR /app
|
|||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Copy entrypoint script
|
||||||
|
COPY docker/entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
# Create necessary directories
|
# Create necessary directories
|
||||||
RUN mkdir -p /app/models /app/data /app/uploads
|
RUN mkdir -p /app/models /app/data /app/uploads
|
||||||
|
|
||||||
# Copy application code
|
# Copy application code
|
||||||
COPY src/ ./src/
|
COPY src/ ./src/
|
||||||
|
|
||||||
|
# Set entrypoint
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
|
||||||
# Set environment variables
|
# Set environment variables
|
||||||
ENV PYTHONPATH=/app
|
ENV PYTHONPATH=/app
|
||||||
ENV PYTHONUNBUFFERED=1
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|||||||
9
docker/entrypoint.sh
Normal file
9
docker/entrypoint.sh
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Create directories if they don't exist and set permissions
|
||||||
|
mkdir -p /app/data /app/uploads /app/models
|
||||||
|
chmod 777 /app/data /app/uploads /app/models
|
||||||
|
|
||||||
|
# Start the application
|
||||||
|
exec "$@"
|
||||||
@@ -6,17 +6,17 @@ jinja2==3.1.3
|
|||||||
aiofiles==23.2.1
|
aiofiles==23.2.1
|
||||||
|
|
||||||
# Whisper
|
# Whisper
|
||||||
openai-whisper==20231117
|
openai-whisper==20240930
|
||||||
faster-whisper==0.10.0
|
faster-whisper==1.1.0
|
||||||
torch==2.1.2
|
torch==2.5.1
|
||||||
torchaudio==2.1.2
|
torchaudio==2.5.1
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
sqlalchemy==2.0.25
|
sqlalchemy==2.0.36
|
||||||
alembic==1.13.1
|
alembic==1.14.0
|
||||||
|
|
||||||
# Audio processing
|
# Audio processing
|
||||||
librosa==0.10.1
|
librosa==0.10.2.post1
|
||||||
soundfile==0.12.1
|
soundfile==0.12.1
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ from sqlalchemy.orm import Session
|
|||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
from src.services.stats_service import hash_api_key
|
||||||
|
from src.database.db import SessionLocal
|
||||||
|
from src.database.models import ApiKey
|
||||||
|
|
||||||
def verify_api_key(authorization: Optional[str] = Header(None)):
|
def verify_api_key(authorization: Optional[str] = Header(None)):
|
||||||
"""Verify API key from Authorization header"""
|
"""Verify API key from Authorization header"""
|
||||||
if not authorization:
|
if not authorization:
|
||||||
@@ -24,16 +28,28 @@ def verify_api_key(authorization: Optional[str] = Header(None)):
|
|||||||
raise HTTPException(status_code=401, detail="Invalid authorization format")
|
raise HTTPException(status_code=401, detail="Invalid authorization format")
|
||||||
|
|
||||||
api_key = authorization.replace("Bearer ", "").strip()
|
api_key = authorization.replace("Bearer ", "").strip()
|
||||||
|
|
||||||
|
# Check environment variable keys first
|
||||||
valid_keys = settings.get_api_keys_list()
|
valid_keys = settings.get_api_keys_list()
|
||||||
|
if api_key in valid_keys:
|
||||||
if not valid_keys:
|
|
||||||
raise HTTPException(status_code=500, detail="No API keys configured")
|
|
||||||
|
|
||||||
if api_key not in valid_keys:
|
|
||||||
raise HTTPException(status_code=401, detail="Invalid API key")
|
|
||||||
|
|
||||||
return api_key
|
return api_key
|
||||||
|
|
||||||
|
# Check database keys
|
||||||
|
db = SessionLocal()
|
||||||
|
try:
|
||||||
|
key_hash = hash_api_key(api_key)
|
||||||
|
db_key = db.query(ApiKey).filter(
|
||||||
|
ApiKey.key_hash == key_hash,
|
||||||
|
ApiKey.is_active == True
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if db_key:
|
||||||
|
return api_key
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
raise HTTPException(status_code=401, detail="Invalid API key")
|
||||||
|
|
||||||
|
|
||||||
@router.get("/models")
|
@router.get("/models")
|
||||||
async def list_models(api_key: str = Depends(verify_api_key)):
|
async def list_models(api_key: str = Depends(verify_api_key)):
|
||||||
|
|||||||
Reference in New Issue
Block a user