from datetime import datetime, timedelta, timezone from typing import Optional, Dict, Any from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from jose import JWTError, jwt import logging from modules.gateway_interface import get_gateway_interface from modules.gateway_model import User, Token import configload # Get Config Data config=configload.load_config() SECRET_KEY = config.get('Access', 'SECRET_KEY') ALGORITHM = config.get('Access', 'ALGORITHM') ACCESS_TOKEN_EXPIRE_MINUTES = int(config.get('Access', 'ACCESS_TOKEN_EXPIRE_MINUTES')) # OAuth2 Setup oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") # Logger logger = logging.getLogger(__name__) def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str: """ Erstellt ein JWT Access Token. Args: data: Zu kodierende Daten (meist Benutzer-ID oder Benutzername) expires_delta: Gültigkeitsdauer des Tokens (optional) Returns: JWT Token als String """ to_encode = data.copy() if expires_delta: expire = datetime.now(timezone.utc) + expires_delta else: expire = datetime.now(timezone.utc) + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) to_encode.update({"exp": expire}) encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) return encoded_jwt async def get_current_user(token: str = Depends(oauth2_scheme)) -> Dict[str, Any]: """ Extrahiert und validiert den aktuellen Benutzer aus dem JWT Token. Args: token: JWT Token aus dem Authorization-Header Returns: Benutzerdaten Raises: HTTPException: Bei ungültigem Token oder Benutzer """ credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Ungültige Authentifizierungsdaten", headers={"WWW-Authenticate": "Bearer"}, ) try: # Token dekodieren payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) # Benutzername aus dem Token extrahieren username: str = payload.get("sub") if username is None: raise credentials_exception # Mandanten-ID aus dem Token extrahieren (falls vorhanden) mandate_id: int = payload.get("mandate_id", 1) # Standard: Root-Mandant except JWTError: logger.warning("Ungültiges JWT Token") raise credentials_exception # Gateway-Interface ohne Kontext initialisieren gateway = get_gateway_interface() # Benutzer aus der Datenbank abrufen user = gateway.get_user_by_username(username) if user is None: logger.warning(f"Benutzer {username} nicht gefunden") raise credentials_exception if user.get("disabled", False): logger.warning(f"Benutzer {username} ist deaktiviert") raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Benutzer ist deaktiviert") return user async def get_current_active_user(current_user: Dict[str, Any] = Depends(get_current_user)) -> Dict[str, Any]: """ Stellt sicher, dass der Benutzer aktiv ist. Args: current_user: Aktuelle Benutzerdaten Returns: Benutzerdaten Raises: HTTPException: Wenn der Benutzer deaktiviert ist """ if current_user.get("disabled", False): raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Benutzer ist deaktiviert") return current_user async def get_user_context(current_user: Dict[str, Any] = Depends(get_current_active_user)) -> tuple: """ Extrahiert den Benutzerkontext (Mandanten-ID und Benutzer-ID). Args: current_user: Aktuelle Benutzerdaten Returns: Tuple mit (mandate_id, user_id) """ mandate_id = current_user.get("mandate_id", 1) # Standard: Root-Mandant user_id = current_user.get("id") return mandate_id, user_id