youtube-summarizer/backend/api/dependencies.py

158 lines
3.8 KiB
Python

"""API Dependencies for authentication and authorization."""
from typing import Optional
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
from core.database import get_db
from services.auth_service import AuthService
from models.user import User
# Bearer token authentication
security = HTTPBearer()
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: Session = Depends(get_db)
) -> User:
"""
Get the current authenticated user from JWT token.
Args:
credentials: Bearer token from Authorization header
db: Database session
Returns:
Current user
Raises:
HTTPException: If authentication fails
"""
token = credentials.credentials
user = AuthService.get_current_user(token, db)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication credentials",
headers={"WWW-Authenticate": "Bearer"},
)
if not user.is_active:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Inactive user"
)
return user
async def get_current_active_user(
current_user: User = Depends(get_current_user)
) -> User:
"""
Get the current active user.
Args:
current_user: Current authenticated user
Returns:
Active user
Raises:
HTTPException: If user is not active
"""
if not current_user.is_active:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Inactive user"
)
return current_user
async def get_verified_user(
current_user: User = Depends(get_current_active_user)
) -> User:
"""
Get a verified user.
Args:
current_user: Current active user
Returns:
Verified user
Raises:
HTTPException: If user is not verified
"""
if not current_user.is_verified:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Please verify your email address"
)
return current_user
async def get_optional_current_user(
credentials: Optional[HTTPAuthorizationCredentials] = Depends(
HTTPBearer(auto_error=False)
),
db: Session = Depends(get_db)
) -> Optional[User]:
"""
Get the current user if authenticated, otherwise None.
Args:
credentials: Bearer token from Authorization header (optional)
db: Database session
Returns:
Current user if authenticated, None otherwise
"""
if not credentials:
return None
token = credentials.credentials
user = AuthService.get_current_user(token, db)
return user
async def get_current_user_ws(
token: Optional[str] = None,
db: Session = Depends(get_db)
) -> Optional[User]:
"""
Get the current user from WebSocket query parameter token (optional authentication).
Args:
token: Optional JWT token from WebSocket query parameter
db: Database session
Returns:
User if token is valid, None otherwise
Note:
This is for WebSocket connections where auth is optional.
Does not raise exceptions like regular auth dependencies.
"""
if not token:
return None
try:
user = AuthService.get_current_user(token, db)
if user and user.is_active:
return user
except Exception:
# Silently fail for WebSocket connections
pass
return None