158 lines
3.8 KiB
Python
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 |