diff --git a/backend/config/__pycache__/app_config.cpython-313.pyc b/backend/config/__pycache__/app_config.cpython-313.pyc index 5847fd80..79d6c64d 100644 Binary files a/backend/config/__pycache__/app_config.cpython-313.pyc and b/backend/config/__pycache__/app_config.cpython-313.pyc differ diff --git a/backend/config/app_config.py b/backend/config/app_config.py index 7715f8b9..36b1ff75 100644 --- a/backend/config/app_config.py +++ b/backend/config/app_config.py @@ -26,7 +26,7 @@ class Config: SESSION_COOKIE_SAMESITE = 'Lax' # Database configuration - DATABASE_URL = os.environ.get('DATABASE_URL') or f'sqlite:///{os.path.join(PROJECT_ROOT, "data", "myp_platform.db")}' + DATABASE_URL = os.environ.get('DATABASE_URL') or f'sqlite:///{os.path.join(PROJECT_ROOT, "database", "myp.db")}' SQLALCHEMY_DATABASE_URI = DATABASE_URL SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_ENGINE_OPTIONS = { diff --git a/backend/database/myp.db-shm b/backend/database/myp.db-shm deleted file mode 100644 index 341c321a..00000000 Binary files a/backend/database/myp.db-shm and /dev/null differ diff --git a/backend/database/myp.db-wal b/backend/database/myp.db-wal deleted file mode 100644 index bcc046ca..00000000 Binary files a/backend/database/myp.db-wal and /dev/null differ diff --git a/backend/database/production.db b/backend/database/production.db deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/docs/DATENBANK_KONFIGURATION.md b/backend/docs/DATENBANK_KONFIGURATION.md new file mode 100644 index 00000000..f9f95c05 --- /dev/null +++ b/backend/docs/DATENBANK_KONFIGURATION.md @@ -0,0 +1,118 @@ +# Datenbank-Konfiguration MYP Platform + +## Übersicht + +Die MYP Platform verwendet **ausschließlich** eine SQLite-Datenbank: + +``` +database/myp.db +``` + +## Konfiguration + +### Haupt-Konfiguration +- **Datei**: `config/settings.py` +- **Variable**: `DATABASE_PATH = os.path.join(BASE_DIR, "database", "myp.db")` +- **Engine**: SQLite mit WAL-Modus (Write-Ahead Logging) + +### Sichergestellte Konsistenz + +Alle folgenden Dateien wurden korrigiert, um ausschließlich `database/myp.db` zu verwenden: + +#### ✅ Konfigurationsdateien +- `config/settings.py` - Haupt-Konfiguration +- `config/app_config.py` - Alternative Flask-Konfiguration (korrigiert) + +#### ✅ Model- und Datenbankdateien +- `models.py` - Hauptmodelle und Engine-Konfiguration +- `database/db_manager.py` - Datenbank-Manager + +#### ✅ Utilities und Tools +- `utils/migrate_db.py` - Datenbank-Migration (Legacy-Fallbacks entfernt) +- `utils/quick_fix.py` - Schnelle Reparatur-Tools (korrigiert) +- `utils/debug_drucker_erkennung.py` - Debug-Tools (korrigiert) +- `utils/database_utils.py` - Backup und Wartung +- `utils/database_cleanup.py` - Cleanup-Manager +- `utils/database_schema_migration.py` - Schema-Migration + +### Entfernte/Korrigierte Inkonsistenzen + +#### 🗑️ Gelöschte Dateien +- `database/production.db` (leer, 0KB) - entfernt + +#### 🔧 Korrigierte Fallbacks +- **Entfernt**: Referenzen zu `app.db`, `database.db`, `data/myp_platform.db` +- **Korrigiert**: Tabellennamen von `printer` zu `printers` +- **Vereinheitlicht**: Alle Import-Pfade verwenden `config.settings.DATABASE_PATH` + +## Verwendung + +### Datenbank initialisieren +```python +from models import init_db +init_db() +``` + +### Session verwenden +```python +from models import get_cached_session + +with get_cached_session() as session: + # Datenbankoperationen + pass +``` + +### Backup erstellen +```python +from utils.database_utils import DatabaseBackupManager + +backup_manager = DatabaseBackupManager() +backup_manager.create_backup() +``` + +## Optimierungen + +Die Datenbank ist für Produktionsumgebung optimiert: + +- **WAL-Modus**: Write-Ahead Logging für bessere Performance +- **Connection Pooling**: Optimierte Verbindungsverwaltung +- **Caching**: Intelligent caching system für häufige Abfragen +- **Auto-Vacuum**: Automatische Speicherbereinigung +- **Indizierung**: Optimierte Indizes für bessere Performance + +## Wartung + +### Automatische Wartung +- WAL-Checkpoints alle 1000 Seiten +- Incremental Vacuum alle 60 Minuten +- Statistik-Updates alle 30 Minuten + +### Manuelle Wartung +```bash +# Migration ausführen +python utils/migrate_db.py + +# Schnelle Reparatur +python utils/quick_fix.py + +# Diagnose +python utils/debug_drucker_erkennung.py +``` + +## Wichtige Hinweise + +⚠️ **NUR `database/myp.db` verwenden!** + +- Keine anderen Datenbankdateien verwenden +- Alle Tools und Scripts sind auf diese Datei konfiguriert +- Bei Problemen: Backup aus `database/backups/` verwenden + +🔒 **Backup-Strategie** +- Automatische Backups in `database/backups/` +- Vor größeren Operationen manuelles Backup erstellen +- WAL- und SHM-Dateien gehören zur Datenbank (nicht löschen!) + +📊 **Monitoring** +- Log-Dateien in `logs/app/` +- Performance-Monitoring via `utils/database_utils.py` +- Health-Checks über API-Endpunkte verfügbar \ No newline at end of file diff --git a/backend/docs/WINDOWS_INSTALLATION.md b/backend/docs/WINDOWS_INSTALLATION.md new file mode 100644 index 00000000..7aac0a98 --- /dev/null +++ b/backend/docs/WINDOWS_INSTALLATION.md @@ -0,0 +1,119 @@ +# MYP Platform - Windows Installation + +## Überblick +Das MYP (Multi-User-Print) System ist ein Flask-basiertes Backend für Druckerverwaltung, das vollständig auf Windows kompatibel ist. + +## Systemanforderungen +- Windows 10/11 +- Python 3.8+ +- Git (optional) +- Internetverbindung für Paketinstallation + +## Installation + +### 1. Python-Abhängigkeiten installieren +```powershell +# Im Projektverzeichnis +pip install -r requirements.txt +``` + +### 2. Datenbank initialisieren +```powershell +python -c "from models import init_database, create_initial_admin; init_database(); create_initial_admin()" +``` + +### 3. Anwendung starten +```powershell +python app.py +``` + +## Automatischer Start (Windows Service) + +### Service-Wrapper erstellen +Das System kann als Windows-Service installiert werden. + +### PowerShell-Skript für automatischen Start +```powershell +# start-myp.ps1 +$env:FLASK_ENV = "production" +$env:FLASK_APP = "app.py" +python app.py +``` + +## Verfügbare Endpunkte +- **Frontend**: http://localhost:5000 +- **API**: http://localhost:5000/api/ +- **Admin**: http://localhost:5000/admin + +## Standard-Login +- **Benutzername**: admin@admin.de +- **Passwort**: admin + +## Konfiguration + +### Ports anpassen +In `app.py` am Ende der Datei: +```python +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5000, debug=False) +``` + +### SSL/HTTPS aktivieren +```python +# SSL-Kontext für HTTPS +ssl_context = ('cert.pem', 'key.pem') +app.run(host="0.0.0.0", port=443, ssl_context=ssl_context) +``` + +## Fehlerbehebung + +### Port bereits in Verwendung +```powershell +# Prozess finden und beenden +netstat -ano | findstr :5000 +taskkill /PID [PID] /F +``` + +### Python-Module fehlen +```powershell +pip install --upgrade pip +pip install -r requirements.txt --force-reinstall +``` + +### Datenbankfehler +```powershell +# Datenbank zurücksetzen +del database\myp.db +python -c "from models import init_database, create_initial_admin; init_database(); create_initial_admin()" +``` + +## Entwicklungsmodus +```powershell +$env:FLASK_ENV = "development" +$env:FLASK_DEBUG = "1" +python app.py +``` + +## Logs +- **Anwendung**: `logs/app/` +- **Authentifizierung**: `logs/auth/` +- **Fehler**: `logs/errors/` +- **Jobs**: `logs/jobs/` + +## Windows-spezifische Features +- Automatische Windows-Kompatibilitätsfixes +- WMI-Integration für Systemüberwachung +- Windows-Event-Log-Integration +- Windows-Service-Support + +## Sicherheit +- CSRF-Schutz aktiviert +- Rate-Limiting implementiert +- Sichere Session-Verwaltung +- SQL-Injection-Schutz + +## Performance-Optimierung +- SQLite-Optimierungen für Windows +- Caching-Strategien +- Asynchrone Task-Verarbeitung +- Memory-Management \ No newline at end of file diff --git a/backend/logs/app/app.log b/backend/logs/app/app.log index ea095462..39a3b7aa 100644 --- a/backend/logs/app/app.log +++ b/backend/logs/app/app.log @@ -84026,3 +84026,4 @@ WHERE printers.active = 1 AND printers.status = ?) AS anon_1] 2025-06-01 01:59:51 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für system_alerts: '>' not supported between instances of 'NoneType' and 'int' 2025-06-01 02:00:01 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für online_printers: tuple index out of range 2025-06-01 02:01:31 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für online_printers: tuple index out of range +2025-06-01 02:03:31 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für system_alerts: '>' not supported between instances of 'NoneType' and 'int' diff --git a/backend/logs/errors/errors.log b/backend/logs/errors/errors.log index 76f64739..f84962ee 100644 --- a/backend/logs/errors/errors.log +++ b/backend/logs/errors/errors.log @@ -1840,3 +1840,4 @@ WHERE printers.active = 1 AND printers.status = ?) AS anon_1] 2025-06-01 01:59:51 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für system_alerts: '>' not supported between instances of 'NoneType' and 'int' 2025-06-01 02:00:01 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für online_printers: tuple index out of range 2025-06-01 02:01:31 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für online_printers: tuple index out of range +2025-06-01 02:03:31 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für system_alerts: '>' not supported between instances of 'NoneType' and 'int' diff --git a/backend/models.py b/backend/models.py index 208c7893..457de1f0 100644 --- a/backend/models.py +++ b/backend/models.py @@ -47,7 +47,7 @@ __all__ = ['User', 'Printer', 'Job', 'Stats', 'SystemLog', 'Base', 'GuestRequest # ===== DATENBANK-KONFIGURATION MIT WAL UND OPTIMIERUNGEN ===== -def configure_sqlite_for_production(dbapi_connection, connection_record): +def configure_sqlite_for_production(dbapi_connection, _connection_record): """ Konfiguriert SQLite für Produktionsumgebung mit WAL-Modus und Optimierungen. """ diff --git a/backend/utils/debug_drucker_erkennung.py b/backend/utils/debug_drucker_erkennung.py index 4e88014d..04bbfbc2 100644 --- a/backend/utils/debug_drucker_erkennung.py +++ b/backend/utils/debug_drucker_erkennung.py @@ -30,40 +30,47 @@ def test_database_connection(): log_message("Teste Datenbankverbindung...") try: - # Versuche SQLite-Datenbank zu öffnen - db_files = ['database.db', 'app.db', 'myp.db'] + # Pfad zur App hinzufügen für korrekten Import + sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) - for db_file in db_files: - if os.path.exists(db_file): - log_message(f"Gefundene Datenbankdatei: {db_file}") - - conn = sqlite3.connect(db_file) - cursor = conn.cursor() - - # Prüfe ob Printer-Tabelle existiert - cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='printer';") - if cursor.fetchone(): - log_message("✅ Printer-Tabelle gefunden") - - # Zähle Drucker - cursor.execute("SELECT COUNT(*) FROM printer;") - count = cursor.fetchone()[0] - log_message(f"📊 Anzahl Drucker in Datenbank: {count}") - - # Zeige Drucker-Details - cursor.execute("SELECT id, name, plug_ip, status FROM printer;") - printers = cursor.fetchall() - - for printer in printers: - log_message(f" Drucker {printer[0]}: {printer[1]} ({printer[2]}) - Status: {printer[3]}") - - conn.close() - return True - else: - log_message("❌ Printer-Tabelle nicht gefunden") - conn.close() + try: + from config.settings import DATABASE_PATH + db_file = DATABASE_PATH + except ImportError: + # Fallback für lokale Ausführung + db_file = os.path.join('database', 'myp.db') + + if os.path.exists(db_file): + log_message(f"Gefundene Datenbankdatei: {db_file}") + + conn = sqlite3.connect(db_file) + cursor = conn.cursor() + + # Prüfe ob Printers-Tabelle existiert + cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='printers';") + if cursor.fetchone(): + log_message("✅ Printers-Tabelle gefunden") + + # Zähle Drucker + cursor.execute("SELECT COUNT(*) FROM printers;") + count = cursor.fetchone()[0] + log_message(f"📊 Anzahl Drucker in Datenbank: {count}") + + # Zeige Drucker-Details + cursor.execute("SELECT id, name, plug_ip, status FROM printers;") + printers = cursor.fetchall() + + for printer in printers: + log_message(f" Drucker {printer[0]}: {printer[1]} ({printer[2]}) - Status: {printer[3]}") + + conn.close() + return True + else: + log_message("❌ Printers-Tabelle nicht gefunden") + conn.close() + else: + log_message(f"❌ Datenbankdatei nicht gefunden: {db_file}") - log_message("❌ Keine gültige Datenbank gefunden") return False except Exception as e: @@ -125,17 +132,21 @@ def test_network_connectivity(): # Lade Drucker aus Datenbank try: - db_files = ['database.db', 'app.db', 'myp.db'] + # Verwende konfigurierten Datenbankpfad + try: + from config.settings import DATABASE_PATH + db_file = DATABASE_PATH + except ImportError: + db_file = os.path.join('database', 'myp.db') + printers = [] - for db_file in db_files: - if os.path.exists(db_file): - conn = sqlite3.connect(db_file) - cursor = conn.cursor() - cursor.execute("SELECT name, plug_ip FROM printer WHERE plug_ip IS NOT NULL;") - printers = cursor.fetchall() - conn.close() - break + if os.path.exists(db_file): + conn = sqlite3.connect(db_file) + cursor = conn.cursor() + cursor.execute("SELECT name, plug_ip FROM printers WHERE plug_ip IS NOT NULL;") + printers = cursor.fetchall() + conn.close() if not printers: log_message("❌ Keine Drucker mit IP-Adressen gefunden") @@ -194,17 +205,21 @@ def test_tapo_connections(): # Lade Drucker aus Datenbank try: - db_files = ['database.db', 'app.db', 'myp.db'] + # Verwende konfigurierten Datenbankpfad + try: + from config.settings import DATABASE_PATH + db_file = DATABASE_PATH + except ImportError: + db_file = os.path.join('database', 'myp.db') + printers = [] - for db_file in db_files: - if os.path.exists(db_file): - conn = sqlite3.connect(db_file) - cursor = conn.cursor() - cursor.execute("SELECT id, name, plug_ip, plug_username, plug_password FROM printer WHERE plug_ip IS NOT NULL;") - printers = cursor.fetchall() - conn.close() - break + if os.path.exists(db_file): + conn = sqlite3.connect(db_file) + cursor = conn.cursor() + cursor.execute("SELECT id, name, plug_ip, plug_username, plug_password FROM printers WHERE plug_ip IS NOT NULL;") + printers = cursor.fetchall() + conn.close() if not printers: log_message("❌ Keine Drucker mit Tapo-Konfiguration gefunden") diff --git a/backend/utils/migrate_db.py b/backend/utils/migrate_db.py index 518f7f13..dd3f6756 100644 --- a/backend/utils/migrate_db.py +++ b/backend/utils/migrate_db.py @@ -34,12 +34,7 @@ def get_database_path(): os.path.join('database', 'myp.db'), 'myp.db', '../database/myp.db', - './database/myp.db', - # Legacy-Pfade für Rückwärtskompatibilität - os.path.join('database', 'app.db'), - 'app.db', - '../database/app.db', - './database/app.db' + './database/myp.db' ] for path in alternative_paths: diff --git a/backend/utils/quick_fix.py b/backend/utils/quick_fix.py index 1f46f321..b21db1a2 100644 --- a/backend/utils/quick_fix.py +++ b/backend/utils/quick_fix.py @@ -5,10 +5,17 @@ Schnelle Datenbank-Reparatur für kritische Fehler import sqlite3 import os +import sys from datetime import datetime -# Datenbankpfad -DATABASE_PATH = "database/myp.db" +# Pfad zur App hinzufügen +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +try: + from config.settings import DATABASE_PATH +except ImportError: + # Fallback falls Import fehlschlägt + DATABASE_PATH = "database/myp.db" def quick_fix_database(): """Behebt die kritischsten Datenbankprobleme sofort"""