From 5aa7da2aa920554ef111fa8e402dd14e1f4ac190 Mon Sep 17 00:00:00 2001 From: Till Tomczak Date: Sun, 1 Jun 2025 02:18:16 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9A=20Improved=20configuration=20files?= =?UTF-8?q?=20&=20documentation=20=F0=9F=93=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__pycache__/app_config.cpython-313.pyc | Bin 7397 -> 7388 bytes backend/config/app_config.py | 2 +- backend/database/myp.db-shm | Bin 32768 -> 0 bytes backend/database/myp.db-wal | Bin 4152 -> 0 bytes backend/database/production.db | 0 backend/docs/DATENBANK_KONFIGURATION.md | 118 +++++++++++++++++ backend/docs/WINDOWS_INSTALLATION.md | 119 ++++++++++++++++++ backend/logs/app/app.log | 1 + backend/logs/errors/errors.log | 1 + backend/models.py | 2 +- backend/utils/debug_drucker_erkennung.py | 115 +++++++++-------- backend/utils/migrate_db.py | 7 +- backend/utils/quick_fix.py | 11 +- 13 files changed, 316 insertions(+), 60 deletions(-) delete mode 100644 backend/database/myp.db-shm delete mode 100644 backend/database/myp.db-wal delete mode 100644 backend/database/production.db create mode 100644 backend/docs/DATENBANK_KONFIGURATION.md create mode 100644 backend/docs/WINDOWS_INSTALLATION.md diff --git a/backend/config/__pycache__/app_config.cpython-313.pyc b/backend/config/__pycache__/app_config.cpython-313.pyc index 5847fd8092beb4170fda4c6065bbf109f8a63d72..79d6c64da5cfa9a80d67da1048b2beb43a65eef6 100644 GIT binary patch delta 89 zcmV-f0H*)tIovr7^9>CO00000hnhQRzOfC_2M!2iVRT_)VRL1A25ot8v+)P30Rc#p voe4Cv)d~Ls9(1sJz#_*d!6(No!7Rvp&|PQHX>rp+a?n9@&^2_k@(lA2=zJwT delta 97 zcmV-n0G|KcIpsMG^9>CO00000n?E&Z!?6v~2NMKjVRT`74{dpHUvO+;bY^dIZL{nL zs{sK_lb8uK17UD*qss{c9(k~Oz#_*d!6(No!7Rvp&|PEDWp>j-chEt2&^39p=?wD^ D%C9F@ 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 341c321a2e286495dcb89884f3e3580cb48c423f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32768 zcmeI*NlrpR5CG6ZoKSHda30ab#1pu1?UHl2(709)<0ZU>hcIqEgVrbfNQ^8rAtCTO zsZ>LMieK*l)s44{C{`__60vxec_-ug{<(E~^YV0c@^SgvY#oh1R^A`#cjt{iKA)x9 ztEl_gwK`wNYG*T_IsZSZofywNk+G1ml2JTYp4W4~nNj5K-<9V@F84*f-)eQ&C~KAZ z=UJAp2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C7`XVqEGqD)UIbC9{FZC5AK!5;&!4s(FT%g%l z%IQMuu`zhB=Z*d$P>;Phh@)smF>lK1Eie&{-iJ;I47I>ydw$$dx2QP+1PBlyK!5-N z0t5&UAV7cs0RjXF5Fjx00&{s!%x>(*VI0RvoDO}z8YJ*7P-)+y^!?e6z~~4}#n$LF lt5X652oNAZfB*pkBPuW*+aub!wh7eQw|H|PK!8ARfiD;+CS?Es diff --git a/backend/database/myp.db-wal b/backend/database/myp.db-wal deleted file mode 100644 index bcc046ca802fa422956395b6c999670e5e625a99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4152 zcmXr7XKP~6eI&uaAiw|wEcPmIZR9r9nu}gh58|}kC<+wg17aDNxY(9t_l;lLV|jss z?0kP2_;2yANPIYH>+?QEDNGF3wD;h({HPFD^+eDJ?csFjQe@5w{gCElw>e zE-uW;EJ=+|EG@~;%u7kFhzE(E5YVwm_)px8PM5`EV9Pp QFd>j#Fg7#*%oKnS0C*pOSO5S3 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"""