scientific-backend / app /dependencies.py
Dama12's picture
feat: backend credit management (2000 daily tokens) with auto-refill logic and deduction API
adc93cc
Raw
History Blame
3.13 kB
"""
Dépendances FastAPI
"""
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session
from typing import Generator
from app.core.security import decode_access_token
from app.db.session import SessionLocal
from app.db.repositories.user_repo import UserRepository
def get_db() -> Generator[Session, None, None]:
"""Dependency pour obtenir une session DB"""
db = SessionLocal()
try:
yield db
finally:
db.close()
security = HTTPBearer()
async def get_current_user(
token: str = None,
credentials: HTTPAuthorizationCredentials = Depends(HTTPBearer(auto_error=False)),
db: Session = Depends(get_db)
):
"""Récupère l'utilisateur courant depuis le token JWT (Supporte Header Bearer et Query Param)"""
token_str = None
if credentials:
token_str = credentials.credentials
elif token:
token_str = token
if not token_str:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Authentication required"
)
payload = decode_access_token(token_str)
if payload is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid token"
)
user_id = payload.get("sub")
if user_id is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid token"
)
# If it's a demo token, bypass DB lookup
if payload.get("demo"):
class MockUser:
def __init__(self, id, email, name):
self.id = id
self.email = email
self.name = name
self.institution = "Demo"
self.role = "Researcher"
self.is_admin = False
self.credits = 2000
return MockUser(user_id, "demo@example.com", "Demo User")
user_repo = UserRepository(db)
try:
user = user_repo.get_by_id(user_id)
if user:
# Automatiquement vérifier le refill à chaque accès
user = user_repo.check_and_refill_credits(user)
except Exception as e:
# If DB is down, we can't verify the user unless it's a demo token
from app.core.logging import logger
logger.error(f"Database error in get_current_user: {e}")
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="Database connection failed. Please use Demo Mode."
)
if user is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="User not found"
)
return user
async def get_admin_user(
current_user = Depends(get_current_user)
):
"""Vérifie que l'utilisateur est admin"""
if not current_user.is_admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Admin access required"
)
return current_user