From d52f39b4eebaa3714d1dc4ea6d3b3626133d8b0e Mon Sep 17 00:00:00 2001
From: valueon
Date: Sun, 16 Mar 2025 16:58:08 +0100
Subject: [PATCH] tokens clean
---
gwserver/app.py | 20 +++----
gwserver/auth.py | 17 +++---
gwserver/config.ini | 15 ++++--
gwserver/configload.py | 11 ++++
gwserver/connector_db_json.py | 3 ++
gwserver/data_gateway/mandates.json | 9 ++++
gwserver/data_gateway/users.json | 13 +++++
gwserver/interface_agentservice.py | 81 ++++++++--------------------
gwserver/interface_gateway.py | 5 +-
gwserver/interface_lucydom.py | 2 +-
gwserver/model_gateway.py | 12 ++++-
requirements.txt | 8 +--
start.sh | 83 +++++++++++++++++++++--------
13 files changed, 164 insertions(+), 115 deletions(-)
create mode 100644 gwserver/configload.py
create mode 100644 gwserver/data_gateway/mandates.json
create mode 100644 gwserver/data_gateway/users.json
diff --git a/gwserver/app.py b/gwserver/app.py
index c181521e..e114ba64 100644
--- a/gwserver/app.py
+++ b/gwserver/app.py
@@ -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:
diff --git a/gwserver/auth.py b/gwserver/auth.py
index 1b97d0af..8f032a4f 100644
--- a/gwserver/auth.py
+++ b/gwserver/auth.py
@@ -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)
diff --git a/gwserver/config.ini b/gwserver/config.ini
index 90ffd97e..9c98fc39 100644
--- a/gwserver/config.ini
+++ b/gwserver/config.ini
@@ -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
diff --git a/gwserver/configload.py b/gwserver/configload.py
new file mode 100644
index 00000000..74792011
--- /dev/null
+++ b/gwserver/configload.py
@@ -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
diff --git a/gwserver/connector_db_json.py b/gwserver/connector_db_json.py
index 864a95e4..a152029c 100644
--- a/gwserver/connector_db_json.py
+++ b/gwserver/connector_db_json.py
@@ -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 []
diff --git a/gwserver/data_gateway/mandates.json b/gwserver/data_gateway/mandates.json
new file mode 100644
index 00000000..d251ec2c
--- /dev/null
+++ b/gwserver/data_gateway/mandates.json
@@ -0,0 +1,9 @@
+[
+ {
+ "id": 1,
+ "name": "Root",
+ "language": "de",
+ "mandate_id": 1,
+ "user_id": 1
+ }
+]
\ No newline at end of file
diff --git a/gwserver/data_gateway/users.json b/gwserver/data_gateway/users.json
new file mode 100644
index 00000000..9d8e710a
--- /dev/null
+++ b/gwserver/data_gateway/users.json
@@ -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
+ }
+]
\ No newline at end of file
diff --git a/gwserver/interface_agentservice.py b/gwserver/interface_agentservice.py
index f5f1f51f..77656f8c 100644
--- a/gwserver/interface_agentservice.py
+++ b/gwserver/interface_agentservice.py
@@ -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 = {
+# Konfigurationsdaten laden
+def load_config_data():
+ config=configload.load_config()
+ result = {
"openai": {
- "api_key": "VOKEY",
- "api_url": "https://api.openai.com/v1/chat/completions",
- "model_name": "gpt-4o"
+ "api_key": config.get('OpenAI', 'API_KEY'),
+ "api_url": config.get('OpenAI', 'API_URL'),
+ "model_name": config.get('OpenAI', 'MODEL_NAME')
},
"application": {
- "debug": "True",
- "upload_dir": "./uploads",
- "results_dir": "./results"
+ "debug": config.get('Application', 'DEBUG'),
+ "upload_dir": config.get('Application', 'UPLOAD_DIR'),
+ "results_dir": config.get('Application', 'RESULTS_DIR')
},
"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"
+ "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')
}
}
-
- 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
- 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"])
- },
- "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"])
- },
- "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"])
- }
- }
-
- # 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
+ # 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
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"]
diff --git a/gwserver/interface_gateway.py b/gwserver/interface_gateway.py
index c5663ae0..8fc726e2 100644
--- a/gwserver/interface_gateway.py
+++ b/gwserver/interface_gateway.py
@@ -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:
diff --git a/gwserver/interface_lucydom.py b/gwserver/interface_lucydom.py
index e3653b0b..6f5248dc 100644
--- a/gwserver/interface_lucydom.py
+++ b/gwserver/interface_lucydom.py
@@ -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
diff --git a/gwserver/model_gateway.py b/gwserver/model_gateway.py
index 7362decd..4ab16aa8 100644
--- a/gwserver/model_gateway.py
+++ b/gwserver/model_gateway.py
@@ -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"""
@@ -57,10 +63,14 @@ class User(BaseModel):
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"})
}
diff --git a/requirements.txt b/requirements.txt
index 181f6d01..d2b9ae5a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -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
diff --git a/start.sh b/start.sh
index 7004af23..c8486531 100644
--- a/start.sh
+++ b/start.sh
@@ -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
\ No newline at end of file
+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
\ No newline at end of file