from datetime import datetime, timedelta from typing import Optional from jose import JWTError, jwt from pydantic import BaseModel from fastapi import Depends, HTTPException, status from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials import pam from app.core.config import settings class TokenData(BaseModel): username: str exp: datetime class Token(BaseModel): access_token: str token_type: str username: str class User(BaseModel): username: str is_authenticated: bool = True def authenticate_user(username: str, password: str) -> Optional[User]: """ Authentifie un utilisateur via PAM (Pluggable Authentication Module) Validé contre le système Debian/Linux """ try: pam_auth = pam.pam() if pam_auth.authenticate(username, password): return User(username=username) return None except Exception as e: print(f"Erreur PAM: {e}") return None def create_access_token(username: str, expires_delta: Optional[timedelta] = None) -> str: """Crée un token JWT""" if expires_delta: expire = datetime.utcnow() + expires_delta else: expire = datetime.utcnow() + timedelta( minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES ) to_encode = {"sub": username, "exp": expire} encoded_jwt = jwt.encode( to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM ) return encoded_jwt security = HTTPBearer() async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)) -> User: """ Valide le token JWT et retourne l'utilisateur actuel """ credential_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Impossible de valider les credentials", headers={"WWW-Authenticate": "Bearer"}, ) try: token = credentials.credentials payload = jwt.decode( token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM] ) username: str = payload.get("sub") if username is None: raise credential_exception token_data = TokenData(username=username, exp=payload.get("exp")) except JWTError: raise credential_exception return User(username=token_data.username)