fix: Restore all files lost during destructive rebase
A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
96
backend/llm_gateway/middleware/auth.py
Normal file
96
backend/llm_gateway/middleware/auth.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""
|
||||
Auth Middleware für LLM Gateway.
|
||||
|
||||
Unterstützt:
|
||||
- API Key Auth (X-API-Key Header oder Authorization Bearer)
|
||||
- JWT Token Auth (vom Consent Service)
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import Optional
|
||||
from fastapi import HTTPException, Header, Depends
|
||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
import jwt
|
||||
|
||||
from ..config import get_config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
security = HTTPBearer(auto_error=False)
|
||||
|
||||
|
||||
async def verify_api_key(
|
||||
x_api_key: Optional[str] = Header(None, alias="X-API-Key"),
|
||||
authorization: Optional[HTTPAuthorizationCredentials] = Depends(security),
|
||||
) -> str:
|
||||
"""
|
||||
Verifiziert den API Key oder JWT Token.
|
||||
|
||||
Akzeptiert:
|
||||
- X-API-Key Header
|
||||
- Authorization: Bearer <token>
|
||||
|
||||
Returns:
|
||||
str: User ID oder "api_key" bei API Key Auth
|
||||
"""
|
||||
config = get_config()
|
||||
|
||||
# 1. Prüfe X-API-Key Header
|
||||
if x_api_key:
|
||||
if x_api_key in config.api_keys:
|
||||
return "api_key"
|
||||
logger.warning(f"Invalid API key attempted")
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail={"error": "unauthorized", "message": "Invalid API key"},
|
||||
)
|
||||
|
||||
# 2. Prüfe Authorization Header
|
||||
if authorization:
|
||||
token = authorization.credentials
|
||||
|
||||
# Prüfe ob es ein API Key ist
|
||||
if token in config.api_keys:
|
||||
return "api_key"
|
||||
|
||||
# Versuche JWT zu dekodieren
|
||||
if config.jwt_secret:
|
||||
try:
|
||||
payload = jwt.decode(
|
||||
token,
|
||||
config.jwt_secret,
|
||||
algorithms=["HS256"],
|
||||
)
|
||||
user_id = payload.get("user_id") or payload.get("sub")
|
||||
if user_id:
|
||||
return str(user_id)
|
||||
except jwt.ExpiredSignatureError:
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail={"error": "token_expired", "message": "Token has expired"},
|
||||
)
|
||||
except jwt.InvalidTokenError as e:
|
||||
logger.warning(f"Invalid JWT token: {e}")
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail={"error": "invalid_token", "message": "Invalid token"},
|
||||
)
|
||||
|
||||
# 3. In Development Mode ohne Auth erlauben
|
||||
if config.debug:
|
||||
logger.warning("Auth bypassed in debug mode")
|
||||
return "debug_user"
|
||||
|
||||
# 4. Keine gültige Auth gefunden
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail={
|
||||
"error": "unauthorized",
|
||||
"message": "API key or valid token required",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def get_current_user_id(user_id: str = Depends(verify_api_key)) -> str:
|
||||
"""Dependency um die aktuelle User ID zu bekommen."""
|
||||
return user_id
|
||||
Reference in New Issue
Block a user