tokens clean

This commit is contained in:
valueon 2025-03-16 16:58:08 +01:00
parent 70bfdc0342
commit d52f39b4ee
13 changed files with 164 additions and 115 deletions

View file

@ -60,28 +60,22 @@ app.add_middleware(
allow_headers=["*"],
)
# Verzeichnis für hochgeladene Dateien erstellen
UPLOAD_DIR = os.path.join(os.getcwd(), "uploads")
os.makedirs(UPLOAD_DIR, exist_ok=True)
# Komponenten des Frontends
app.mount("/static", StaticFiles(directory="static"), name="static")
# API - ENDPUNKTE
# Statischer Folder für Frontend
os.makedirs(os.path.join(os.getcwd(), "static"), exist_ok=True)
app.mount("/static", StaticFiles(directory="static"), name="static")
# Generelle Elements
@app.get("/", tags=["General"])
async def root():
"""API-Statusendpunkt"""
return {"status": "online", "message": "Data Platform API ist aktiv"}
# Test Element
@app.get("/api/test", tags=["Test"])
@app.get("/api/test", tags=["General"])
async def get_test():
return "OK 1.0"
# Token-Endpunkt für Login
@app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
@ -265,7 +259,7 @@ async def upload_file(
# Generiere eine eindeutige ID für die Datei
file_id = str(uuid.uuid4())
file_ext = os.path.splitext(file.filename)[1]
file_path = os.path.join(UPLOAD_DIR, f"{file_id}{file_ext}")
file_path = os.path.join(get_agent_service(mandate_id, user_id).upload_dir, f"{file_id}{file_ext}")
# Datei speichern
with open(file_path, "wb") as f:

View file

@ -1,4 +1,4 @@
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from typing import Optional, Dict, Any
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
@ -6,12 +6,15 @@ from jose import JWTError, jwt
import logging
from interface_gateway import get_gateway_interface
from model_gateway import User, Token
import configload
# Konfigurationsvariablen
SECRET_KEY = "dein-geheimer-schlüssel" # In Produktion aus Umgebungsvariablen laden!
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 600
# 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")
@ -34,9 +37,9 @@ def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
expire = datetime.now(timezone.utc) + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
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)

View file

@ -1,13 +1,18 @@
[OpenAI]
API_KEY = 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
API_URL = https://api.openai.com/v1/chat/completions
MODEL_NAME = gpt-4o
[Application]
DEBUG = True
UPLOAD_DIR = ./uploads
RESULTS_DIR = ./results
[Access]
SECRET_KEY = dein-geheimer-schlüssel
ALGORITHM = HS256
ACCESS_TOKEN_EXPIRE_MINUTES = 300
[OpenAI]
API_KEY = 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
API_URL = https://api.openai.com/v1/chat/completions
MODEL_NAME = gpt-4o
[WebScraping]
TIMEOUT = 10
MAX_URLS = 3

11
gwserver/configload.py Normal file
View file

@ -0,0 +1,11 @@
import configparser
import os
# Konfiguration aus config.ini laden
def load_config():
config = configparser.ConfigParser()
config_path = os.path.join(os.path.dirname(__file__), 'config.ini')
if not os.path.exists(config_path):
exit("No config file")
config.read(config_path)
return config

View file

@ -56,17 +56,20 @@ class JSONDatabaseConnector:
# Wenn die Tabelle bereits im Cache ist, verwende den Cache
if table in self._tables_cache:
logger.info(f"Lade Tabelle {table} aus Cache")
return self._tables_cache[table]
# Ansonsten lade die Datei
try:
if os.path.exists(path):
logger.info(f"Lade Tabelle {table} aus JSON {path}")
with open(path, 'r', encoding='utf-8') as f:
data = json.load(f)
self._tables_cache[table] = data
return data
else:
# Wenn die Datei nicht existiert, erstelle eine leere Tabelle
logger.info(f"Neue Tabelle {table}")
self._tables_cache[table] = []
self._save_table(table, [])
return []

View file

@ -0,0 +1,9 @@
[
{
"id": 1,
"name": "Root",
"language": "de",
"mandate_id": 1,
"user_id": 1
}
]

View file

@ -0,0 +1,13 @@
[
{
"id": 1,
"mandate_id": 1,
"username": "admin",
"email": "admin@example.com",
"full_name": "Administrator",
"disabled": false,
"language": "de",
"hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$tJYSAmDs/T+HEALg3Nsbww$2HnCW69CkCkk82fgRhzjYtdNu3b9G7NmSJZmbUQVDOs",
"user_id": 1
}
]

View file

@ -3,84 +3,47 @@ import uuid
import os
import json
import logging
import time
import configparser
import re
from typing import List, Dict, Any, Optional
from datetime import datetime
import sys
import httpx
from fastapi import HTTPException
import requests
from bs4 import BeautifulSoup
import configload as configload
# Logger konfigurieren
logger = logging.getLogger(__name__)
# Konfiguration aus config.ini laden
def load_config():
config = configparser.ConfigParser()
config_path = os.path.join(os.path.dirname(__file__), 'config.ini')
# Standardkonfiguration
default_config = {
"openai": {
"api_key": "VOKEY",
"api_url": "https://api.openai.com/v1/chat/completions",
"model_name": "gpt-4o"
},
"application": {
"debug": "True",
"upload_dir": "./uploads",
"results_dir": "./results"
},
"webscraping": {
"timeout": "10",
"max_urls": "3",
"max_content_length": "3000",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}
}
if not os.path.exists(config_path):
logger.warning(f"Konfigurationsdatei nicht gefunden: {config_path}")
return default_config
try:
config.read(config_path)
# Konfiguration aus der Datei lesen
# Konfigurationsdaten laden
def load_config_data():
config=configload.load_config()
result = {
"openai": {
"api_key": config.get('OpenAI', 'API_KEY', fallback=default_config["openai"]["api_key"]),
"api_url": config.get('OpenAI', 'API_URL', fallback=default_config["openai"]["api_url"]),
"model_name": config.get('OpenAI', 'MODEL_NAME', fallback=default_config["openai"]["model_name"])
"api_key": config.get('OpenAI', 'API_KEY'),
"api_url": config.get('OpenAI', 'API_URL'),
"model_name": config.get('OpenAI', 'MODEL_NAME')
},
"application": {
"debug": config.get('Application', 'DEBUG', fallback=default_config["application"]["debug"]),
"upload_dir": config.get('Application', 'UPLOAD_DIR', fallback=default_config["application"]["upload_dir"]),
"results_dir": config.get('Application', 'RESULTS_DIR', fallback=default_config["application"]["results_dir"])
"debug": config.get('Application', 'DEBUG'),
"upload_dir": config.get('Application', 'UPLOAD_DIR'),
"results_dir": config.get('Application', 'RESULTS_DIR')
},
"webscraping": {
"timeout": config.get('WebScraping', 'TIMEOUT', fallback=default_config["webscraping"]["timeout"]),
"max_urls": config.get('WebScraping', 'MAX_URLS', fallback=default_config["webscraping"]["max_urls"]),
"max_content_length": config.get('WebScraping', 'MAX_CONTENT_LENGTH', fallback=default_config["webscraping"]["max_content_length"]),
"user_agent": config.get('WebScraping', 'USER_AGENT', fallback=default_config["webscraping"]["user_agent"])
"timeout": config.get('WebScraping', 'TIMEOUT'),
"max_urls": config.get('WebScraping', 'MAX_URLS'),
"max_content_length": config.get('WebScraping', 'MAX_CONTENT_LENGTH'),
"user_agent": config.get('WebScraping', 'USER_AGENT')
}
}
# Debug-Modus einstellen
if result["application"]["debug"].lower() == "true":
logging.basicConfig(level=logging.DEBUG)
logger.setLevel(logging.DEBUG)
logger.debug("Debug-Modus aktiviert")
return result
except Exception as e:
logger.error(f"Fehler beim Laden der Konfiguration: {e}")
return default_config
class AgentService:
@ -101,7 +64,7 @@ class AgentService:
self.user_id = user_id
# Konfiguration laden
self.config = load_config()
self.config = load_config_data()
# Verzeichnisse aus der Konfiguration übernehmen
self.results_dir = self.config["application"]["results_dir"]

View file

@ -11,7 +11,7 @@ logger = logging.getLogger(__name__)
# Password-Hashing
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
pwd_context = CryptContext(schemes=["argon2"], deprecated="auto")
class GatewayInterface:
@ -33,8 +33,9 @@ class GatewayInterface:
self.user_id = user_id if user_id is not None else 1 # Admin-Benutzer als Standard
# Datenverzeichnis
self.data_folder = "/data_gateway"
self.data_folder = "data_gateway"
os.makedirs(self.data_folder, exist_ok=True)
logger.info("db for data_gateway atteached")
# Datenmodell-Modul importieren
try:

View file

@ -26,7 +26,7 @@ class LucyDOMInterface:
self.user_id = user_id
# Datenverzeichnis
self.data_folder = "/data_lucydom"
self.data_folder = "data_lucydom"
os.makedirs(self.data_folder, exist_ok=True)
# Datenmodell-Modul importieren

View file

@ -26,6 +26,12 @@ class Mandate(BaseModel):
description="Label für die Klasse"
)
# Labels für Attribute
field_labels: Dict[str, Label] = {
"id": Label(default="ID", translations={}),
"name": Label(default="Name des Mandanten", translations={"en": "Mandate name", "fr": "Nom du mandat"}),
"language": Label(default="Sprache", translations={"en": "Language", "fr": "Langue"})
}
class User(BaseModel):
"""Datenmodell für einen Benutzer"""
@ -58,9 +64,13 @@ class UserInDB(User):
"""Erweiterte Benutzerklasse mit Passwort-Hash"""
hashed_password: str = Field(description="Hash des Benutzerpassworts")
label: Label = Field(
default=Label(default="Benutzer Zugriff", translations={"en": "User Access", "fr": "Accès de l'utilisateur"}),
description="Label für die Klasse"
)
# Zusätzliches Label für das Passwort-Feld
field_labels: Dict[str, Label] = {
**User.field_labels,
"hashed_password": Label(default="Passwort-Hash", translations={"en": "Password hash", "fr": "Hachage de mot de passe"})
}

View file

@ -11,7 +11,7 @@ email-validator>=2.0.0 # For email validation
# Authentication and Security
python-jose>=3.3.0 # For JWT
passlib>=1.7.4 # For password hashing
bcrypt>=4.0.1 # For password hashing
argon2-cffi # For password hashing
cryptography>=40.0.2 # Required by jose
# Utilities
@ -55,9 +55,9 @@ aiofiles>=23.1.0 # Async file operations
# AI and NLP
openai>=0.27.4 # OpenAI API client
nltk>=3.8.1 # Natural Language Toolkit
scikit-learn>=1.2.2 # For machine learning utilities
spacy>=3.5.2 # For advanced NLP
#nltk>=3.8.1 # Natural Language Toolkit
#scikit-learn>=1.2.2 # For machine learning utilities
#spacy>=3.5.2 # For advanced NLP
# Visualization (for generating reports)
matplotlib>=3.7.1

View file

@ -1,21 +1,23 @@
#!/bin/bash
# Farben für die Ausgabe
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Erkennen des Betriebssystems
case "$(uname -s)" in
CYGWIN*|MINGW*|MSYS*|Windows*)
OS="Windows"
VENV_PATH="gwserver/venv/Scripts"
ACTIVATE_CMD="$VENV_PATH/activate"
;;
*)
OS="Unix"
VENV_PATH="gwserver/venv/bin"
ACTIVATE_CMD="$VENV_PATH/activate"
;;
esac
echo -e "${GREEN}Data Platform - Multi-Agent Service${NC}"
echo -e "${BLUE}Startskript für gwserver${NC}"
echo "----------------------------------------"
# Verzeichnisstruktur erstellen, falls sie nicht existiert
mkdir -p gwserver/data
mkdir -p gwserver/uploads
mkdir -p gwserver/results
mkdir -p gwserver/static
echo "Erkanntes Betriebssystem: $OS"
# Prüfen, ob Python installiert ist
PYTHON_CMD=""
if command -v python3 &>/dev/null; then
PYTHON_CMD="python3"
elif command -v python &>/dev/null; then
@ -35,7 +37,11 @@ fi
# Virtuelle Umgebung aktivieren
echo "Aktiviere virtuelle Umgebung..."
source gwserver/venv/bin/activate 2>/dev/null || . gwserver/venv/bin/activate
if [ "$OS" = "Windows" ]; then
source "$ACTIVATE_CMD" 2>/dev/null || . "$ACTIVATE_CMD" 2>/dev/null || echo "Warnung: Aktivierung der virtuellen Umgebung fehlgeschlagen. Fahre fort..."
else
source "$ACTIVATE_CMD" 2>/dev/null || . "$ACTIVATE_CMD" 2>/dev/null || echo "Warnung: Aktivierung der virtuellen Umgebung fehlgeschlagen. Fahre fort..."
fi
# Abhängigkeiten installieren
echo "Installiere Abhängigkeiten..."
@ -43,20 +49,38 @@ pip install -r requirements.txt
# gwserver als Hintergrundprozess starten
echo "Starte gwserver-Server..."
cd gwserver
uvicorn app:app --reload --host 0.0.0.0 --port 8000 &
GWSERVER_PID=$!
cd ..
echo "----------------------------------------"
# START CORE
cd gwserver
if [ "$OS" = "Windows" ]; then
# Windows: starte in einem separaten Prozess
start uvicorn app:app --reload --host 0.0.0.0 --port 8000
# Keine PID-Erfassung nötig unter Windows mit 'start'
GWSERVER_PID=""
else
# Unix: starte im Hintergrund und erfasse PID
uvicorn app:app --reload --host 0.0.0.0 --port 8000 &
GWSERVER_PID=$!
fi
# END CORE
cd ..
echo "gwserver API läuft auf: http://localhost:8000"
echo "API-Dokumentation: http://localhost:8000/docs"
echo -e "${BLUE}Drücke STRG+C, um Server zu beenden${NC}"
echo "Drücke STRG+C, um Server zu beenden"
# Funktion zum Beenden der Server bei STRG+C
cleanup() {
echo -e "\n${GREEN}Beende Server...${NC}"
kill $GWSERVER_PID
echo -e "\nBeende Server..."
if [ "$OS" = "Windows" ]; then
# Windows: Taskkill für uvicorn
taskkill //F //IM uvicorn.exe 2>/dev/null || echo "Konnte uvicorn nicht beenden"
else
# Unix: Verwende die erfasste PID
if [ -n "$GWSERVER_PID" ]; then
kill $GWSERVER_PID 2>/dev/null || echo "Konnte Prozess $GWSERVER_PID nicht beenden"
fi
fi
echo "Server wurden beendet"
exit 0
}
@ -65,4 +89,17 @@ cleanup() {
trap cleanup SIGINT
# Warten auf Benutzeraktion
wait
if [ "$OS" = "Windows" ]; then
# Unter Windows: Warte auf Eingabe
read -p "Drücke Enter zum Beenden..." dummy
cleanup
else
# Unter Unix: Warte auf Prozess
if [ -n "$GWSERVER_PID" ]; then
wait $GWSERVER_PID
else
# Fallback: einfach warten
read -p "Drücke Enter zum Beenden..." dummy
cleanup
fi
fi