gateway/gwserver/auth.py
2025-03-16 14:19:47 +01:00

131 lines
No EOL
3.9 KiB
Python

from datetime import datetime, timedelta
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 interface_gateway import get_gateway_interface
from model_gateway import User, Token
# Konfigurationsvariablen
SECRET_KEY = "dein-geheimer-schlüssel" # In Produktion aus Umgebungsvariablen laden!
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 600
# 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.utcnow() + expires_delta
else:
expire = datetime.utcnow() + 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