feat: Add admin auth
This commit is contained in:
parent
046504e6a1
commit
e05a62cda9
4 changed files with 21 additions and 5 deletions
|
|
@ -48,3 +48,18 @@ def verify_token(
|
||||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
detail="Invalid or expired token",
|
detail="Invalid or expired token",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _admin_emails() -> frozenset[str]:
|
||||||
|
return frozenset(
|
||||||
|
e.strip() for e in settings.admin_user_emails.split(",") if e.strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def require_admin(token_data: dict = Depends(verify_token)) -> dict:
|
||||||
|
if token_data.get("email") not in _admin_emails():
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail="Admin access required",
|
||||||
|
)
|
||||||
|
return token_data
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ class Settings(BaseSettings):
|
||||||
deepl_api_key: str
|
deepl_api_key: str
|
||||||
deepgram_api_key: str
|
deepgram_api_key: str
|
||||||
gemini_api_key: str
|
gemini_api_key: str
|
||||||
|
admin_user_emails: str = "" # comma-separated list of admin email addresses
|
||||||
storage_endpoint_url: str
|
storage_endpoint_url: str
|
||||||
storage_access_key: str
|
storage_access_key: str
|
||||||
storage_secret_key: str
|
storage_secret_key: str
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ from pydantic import BaseModel
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from ...languages import SUPPORTED_LANGUAGES, SUPPORTED_LEVELS
|
from ...languages import SUPPORTED_LANGUAGES, SUPPORTED_LEVELS
|
||||||
from ...auth import verify_token
|
from ...auth import require_admin
|
||||||
from ...storage import upload_audio
|
from ...storage import upload_audio
|
||||||
from ...outbound.postgres.database import get_db, AsyncSessionLocal
|
from ...outbound.postgres.database import get_db, AsyncSessionLocal
|
||||||
from ...outbound.postgres.repositories import summarise_job_repository
|
from ...outbound.postgres.repositories import summarise_job_repository
|
||||||
|
|
@ -125,7 +125,7 @@ async def _run_generation(job_id: uuid.UUID, request: GenerationRequest) -> None
|
||||||
async def create_generation_job(
|
async def create_generation_job(
|
||||||
request: GenerationRequest,
|
request: GenerationRequest,
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
token_data: dict = Depends(verify_token),
|
token_data: dict = Depends(require_admin),
|
||||||
) -> GenerationResponse:
|
) -> GenerationResponse:
|
||||||
if request.target_language not in SUPPORTED_LANGUAGES:
|
if request.target_language not in SUPPORTED_LANGUAGES:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ from fastapi import APIRouter, Depends, HTTPException
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from ...auth import verify_token
|
from ...auth import require_admin
|
||||||
from ...outbound.postgres.database import get_db, AsyncSessionLocal
|
from ...outbound.postgres.database import get_db, AsyncSessionLocal
|
||||||
from ...outbound.postgres.repositories import summarise_job_repository
|
from ...outbound.postgres.repositories import summarise_job_repository
|
||||||
from ...outbound.gemini.gemini_client import GeminiClient
|
from ...outbound.gemini.gemini_client import GeminiClient
|
||||||
|
|
@ -14,7 +14,7 @@ from ...storage import upload_audio
|
||||||
from ...config import settings
|
from ...config import settings
|
||||||
from ... import worker
|
from ... import worker
|
||||||
|
|
||||||
router = APIRouter(prefix="/jobs", dependencies=[Depends(verify_token)])
|
router = APIRouter(prefix="/jobs", dependencies=[Depends(require_admin)])
|
||||||
|
|
||||||
|
|
||||||
class JobResponse(BaseModel):
|
class JobResponse(BaseModel):
|
||||||
|
|
@ -124,7 +124,7 @@ async def _run_regenerate_audio(job_id: uuid.UUID) -> None:
|
||||||
async def regenerate_audio(
|
async def regenerate_audio(
|
||||||
job_id: str,
|
job_id: str,
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
token_data: dict = Depends(verify_token),
|
token_data: dict = Depends(require_admin),
|
||||||
) -> dict:
|
) -> dict:
|
||||||
try:
|
try:
|
||||||
uid = uuid.UUID(job_id)
|
uid = uuid.UUID(job_id)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue