from fastapi import APIRouter, HTTPException, status, Form, Request, Depends from datetime import timedelta from slowapi import Limiter from slowapi.util import get_remote_address from app.core.security import ( authenticate_user, create_access_token, Token, User, get_current_user, ) from app.core.config import settings import logging logger = logging.getLogger("innotexboard.security") limiter = Limiter(key_func=get_remote_address) router = APIRouter() @router.post("/login", response_model=Token) @limiter.limit("5/minute") # Max 5 tentatives par minute par IP async def login( request: Request, username: str = Form(..., min_length=2, max_length=32), password: str = Form(..., min_length=1) ): """ Endpoint d'authentification PAM avec protection brute force Authentifie l'utilisateur contre le système Debian via PAM """ client_ip = get_remote_address(request) # Log de la tentative de connexion logger.info(f"Login attempt for user '{username}' from {client_ip}") # Validation et authentification user = authenticate_user(username, password, client_ip) if not user: logger.warning(f"Failed login for '{username}' from {client_ip}") raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Identifiants incorrects", headers={"WWW-Authenticate": "Bearer"}, ) # Génération du token access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) access_token = create_access_token( username=user.username, expires_delta=access_token_expires ) logger.info(f"Successful login for '{username}' from {client_ip}") return { "access_token": access_token, "token_type": "bearer", "username": user.username, } @router.get("/me", response_model=User) async def read_users_me(current_user: User = Depends(get_current_user)): """Retourne les informations de l'utilisateur actuellement authentifié""" return current_user @router.post("/logout") async def logout( request: Request, current_user: User = Depends(get_current_user) ): """Endpoint de déconnexion (le token devient simplement invalide côté client)""" client_ip = get_remote_address(request) logger.info(f"User '{current_user.username}' logged out from {client_ip}") return {"message": "Déconnecté avec succès"}