Dashboard Finished

This commit is contained in:
2025-10-07 08:44:02 +02:00
parent 68d4fc9a36
commit b5a85c610a
6 changed files with 53 additions and 19 deletions

View File

@@ -1,4 +1,5 @@
import os import os
from pathlib import Path
from typing import Any, Dict from typing import Any, Dict
@@ -10,7 +11,15 @@ class DatabaseConfig:
def _load_config(self) -> Dict[str, Any]: def _load_config(self) -> Dict[str, Any]:
if self.db_type.lower() == "sqlite": if self.db_type.lower() == "sqlite":
return {"path": os.getenv("SQLITE_PATH", "databases/chatbot.db")} # Standardpfad relativ zum Projektroot
default_path = Path(__file__).parent.parent / "databases" / "chatbot.db"
sqlite_path = os.getenv("SQLITE_PATH", str(default_path))
# Stelle sicher, dass wir einen absoluten Pfad haben
if not Path(sqlite_path).is_absolute():
sqlite_path = Path.cwd() / sqlite_path
return {"path": str(sqlite_path)}
elif self.db_type.lower() == "mysql": elif self.db_type.lower() == "mysql":
return { return {
"host": os.getenv("MYSQL_HOST", "localhost"), "host": os.getenv("MYSQL_HOST", "localhost"),

View File

@@ -1,5 +1,6 @@
import logging import logging
import sqlite3 import sqlite3
from pathlib import Path
from threading import local from threading import local
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
@@ -13,32 +14,50 @@ class SQLiteDatabase(DatabaseInterface):
def __init__(self, db_path: str): def __init__(self, db_path: str):
self.db_path = db_path self.db_path = db_path
# Erstelle Verzeichnis falls nicht vorhanden
self._ensure_database_directory()
# Thread-local storage für Verbindungen # Thread-local storage für Verbindungen
self._local = local() self._local = local()
def _ensure_database_directory(self) -> None:
"""Stellt sicher, dass das Database-Verzeichnis existiert"""
db_dir = Path(self.db_path).parent
if not db_dir.exists():
try:
db_dir.mkdir(parents=True, exist_ok=True)
logger.info(f"Created database directory: {db_dir}")
except OSError as e:
logger.error(f"Failed to create database directory {db_dir}: {e}")
raise
def _get_connection(self) -> sqlite3.Connection: def _get_connection(self) -> sqlite3.Connection:
"""Holt oder erstellt eine thread-lokale Verbindung""" """Holt oder erstellt eine thread-lokale Verbindung"""
if not hasattr(self._local, "connection") or self._local.connection is None: if not hasattr(self._local, "connection") or self._local.connection is None:
self._local.connection = sqlite3.connect( try:
self.db_path, # Absoluten Pfad verwenden für bessere Kompatibilität
check_same_thread=False, # Erlaubt thread-übergreifende Nutzung abs_path = Path(self.db_path).resolve()
timeout=30.0, self._local.connection = sqlite3.connect(
detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES, str(abs_path),
) check_same_thread=False, # Erlaubt thread-übergreifende Nutzung
self._local.connection.row_factory = sqlite3.Row timeout=30.0,
# Optimierungen für bessere Performance detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES,
self._local.connection.execute("PRAGMA journal_mode=WAL") )
self._local.connection.execute("PRAGMA synchronous=NORMAL") self._local.connection.row_factory = sqlite3.Row
self._local.connection.execute("PRAGMA cache_size=1000") # Optimierungen für bessere Performance
self._local.connection.execute("PRAGMA temp_store=MEMORY") self._local.connection.execute("PRAGMA journal_mode=WAL")
logger.debug("New SQLite connection created for thread") self._local.connection.execute("PRAGMA synchronous=NORMAL")
self._local.connection.execute("PRAGMA cache_size=1000")
self._local.connection.execute("PRAGMA temp_store=MEMORY")
logger.debug(f"New SQLite connection created for thread: {abs_path}")
except sqlite3.Error as e:
logger.error(f"Failed to connect to SQLite database at {abs_path}: {e}")
raise
return self._local.connection return self._local.connection
def connect(self) -> None: def connect(self) -> None:
"""Initialisiert die thread-lokale Verbindung""" """Initialisiert die thread-lokale Verbindung"""
try: try:
conn = self._get_connection() self._get_connection() # Entfernt das unbenutzte 'conn'
logger.info(f"Connected to SQLite database: {self.db_path}") logger.info(f"Connected to SQLite database: {self.db_path}")
except Exception as e: except Exception as e:
logger.error(f"Failed to connect to SQLite database: {e}") logger.error(f"Failed to connect to SQLite database: {e}")

View File

@@ -12,7 +12,9 @@ class UserService:
def __init__(self, database: DatabaseInterface): def __init__(self, database: DatabaseInterface):
self.db = database self.db = database
def create_user(self, username: str, email: str, password: str) -> tuple[bool, list[str]]: def create_user(
self, username: str, email: str, password: str
) -> tuple[bool, list[str]]:
errors = self._validate_user_inputs(username, email, password) errors = self._validate_user_inputs(username, email, password)
if errors: if errors:
return False, errors return False, errors
@@ -24,7 +26,9 @@ class UserService:
password_hash = PasswordUtils.hash_password_simple(password) password_hash = PasswordUtils.hash_password_simple(password)
return self._attempt_user_creation(username, email, password_hash) return self._attempt_user_creation(username, email, password_hash)
def _validate_user_inputs(self, username: str, email: str, password: str) -> list[str]: def _validate_user_inputs(
self, username: str, email: str, password: str
) -> list[str]:
errors = [] errors = []
if not ValidationUtils.validate_username(username): if not ValidationUtils.validate_username(username):
errors.append("Invalid username format") errors.append("Invalid username format")
@@ -43,7 +47,9 @@ class UserService:
errors.append("Username already taken") errors.append("Username already taken")
return errors return errors
def _attempt_user_creation(self, username: str, email: str, password_hash: str) -> tuple[bool, list[str]]: def _attempt_user_creation(
self, username: str, email: str, password_hash: str
) -> tuple[bool, list[str]]:
try: try:
success = self.db.create_user(username, email.lower(), password_hash) success = self.db.create_user(username, email.lower(), password_hash)
if success: if success: