feat: Major updates to backend structure and security enhancements
- Removed `COMMON_ERRORS.md` file to streamline documentation. - Added `Flask-Limiter` for rate limiting and `redis` for session management in `requirements.txt`. - Expanded `ROADMAP.md` to include completed security features and planned enhancements for version 2.2. - Enhanced `setup_myp.sh` for ultra-secure kiosk installation, including system hardening and security configurations. - Updated `app.py` to integrate CSRF protection and improved logging setup. - Refactored user model to include username and active status for better user management. - Improved job scheduler with uptime tracking and task management features. - Updated various templates for a more cohesive user interface and experience.
This commit is contained in:
152
backend/app/migrate_db.py
Normal file
152
backend/app/migrate_db.py
Normal file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env python3.11
|
||||
"""
|
||||
Datenbank-Migrationsskript für MYP Platform
|
||||
|
||||
Dieses Skript führt notwendige Änderungen an der Datenbankstruktur durch,
|
||||
um sie mit den neuesten Modellen kompatibel zu machen.
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
import os
|
||||
from datetime import datetime
|
||||
from config.settings import DATABASE_PATH, ensure_database_directory
|
||||
|
||||
def migrate_database():
|
||||
"""Führt alle notwendigen Datenbankmigrationen durch."""
|
||||
ensure_database_directory()
|
||||
|
||||
if not os.path.exists(DATABASE_PATH):
|
||||
print("Datenbank existiert nicht. Führe init_db.py aus, um sie zu erstellen.")
|
||||
return False
|
||||
|
||||
conn = sqlite3.connect(DATABASE_PATH)
|
||||
cursor = conn.cursor()
|
||||
|
||||
print("Starte Datenbankmigration...")
|
||||
|
||||
try:
|
||||
# Migration 1: Füge username-Feld zu users-Tabelle hinzu
|
||||
try:
|
||||
cursor.execute("ALTER TABLE users ADD COLUMN username VARCHAR(100)")
|
||||
print("✓ Username-Feld zur users-Tabelle hinzugefügt")
|
||||
except sqlite3.OperationalError as e:
|
||||
if "duplicate column name" in str(e).lower():
|
||||
print("✓ Username-Feld bereits vorhanden")
|
||||
else:
|
||||
raise e
|
||||
|
||||
# Migration 2: Füge active-Feld zu users-Tabelle hinzu
|
||||
try:
|
||||
cursor.execute("ALTER TABLE users ADD COLUMN active BOOLEAN DEFAULT 1")
|
||||
print("✓ Active-Feld zur users-Tabelle hinzugefügt")
|
||||
except sqlite3.OperationalError as e:
|
||||
if "duplicate column name" in str(e).lower():
|
||||
print("✓ Active-Feld bereits vorhanden")
|
||||
else:
|
||||
raise e
|
||||
|
||||
# Migration 3: Setze username für bestehende Benutzer
|
||||
cursor.execute("SELECT id, email, username FROM users WHERE username IS NULL OR username = ''")
|
||||
users_without_username = cursor.fetchall()
|
||||
|
||||
for user_id, email, username in users_without_username:
|
||||
if not username:
|
||||
# Generiere username aus email (Teil vor @)
|
||||
new_username = email.split('@')[0] if '@' in email else f"user_{user_id}"
|
||||
cursor.execute("UPDATE users SET username = ? WHERE id = ?", (new_username, user_id))
|
||||
print(f"✓ Username '{new_username}' für Benutzer {email} gesetzt")
|
||||
|
||||
# Migration 4: Prüfe und korrigiere Job-Tabelle falls nötig
|
||||
try:
|
||||
# Prüfe ob die Tabelle die neuen Felder hat
|
||||
cursor.execute("PRAGMA table_info(jobs)")
|
||||
columns = [row[1] for row in cursor.fetchall()]
|
||||
|
||||
if 'duration_minutes' not in columns:
|
||||
cursor.execute("ALTER TABLE jobs ADD COLUMN duration_minutes INTEGER")
|
||||
print("✓ Duration_minutes-Feld zur jobs-Tabelle hinzugefügt")
|
||||
|
||||
# Setze Standardwerte für bestehende Jobs (60 Minuten)
|
||||
cursor.execute("UPDATE jobs SET duration_minutes = 60 WHERE duration_minutes IS NULL")
|
||||
print("✓ Standardwerte für duration_minutes gesetzt")
|
||||
|
||||
# Prüfe ob title zu name umbenannt werden muss
|
||||
if 'title' in columns and 'name' not in columns:
|
||||
# SQLite unterstützt kein direktes Umbenennen von Spalten
|
||||
# Wir müssen die Tabelle neu erstellen
|
||||
print("⚠ Konvertierung von 'title' zu 'name' in jobs-Tabelle...")
|
||||
|
||||
# Backup der Daten
|
||||
cursor.execute("""
|
||||
CREATE TABLE jobs_backup AS
|
||||
SELECT * FROM jobs
|
||||
""")
|
||||
|
||||
# Lösche alte Tabelle
|
||||
cursor.execute("DROP TABLE jobs")
|
||||
|
||||
# Erstelle neue Tabelle mit korrekter Struktur
|
||||
cursor.execute("""
|
||||
CREATE TABLE jobs (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
description VARCHAR(500),
|
||||
user_id INTEGER NOT NULL,
|
||||
printer_id INTEGER NOT NULL,
|
||||
start_at DATETIME,
|
||||
end_at DATETIME,
|
||||
actual_end_time DATETIME,
|
||||
status VARCHAR(20) DEFAULT 'scheduled',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
notes VARCHAR(500),
|
||||
material_used FLOAT,
|
||||
file_path VARCHAR(500),
|
||||
owner_id INTEGER,
|
||||
duration_minutes INTEGER NOT NULL DEFAULT 60,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
FOREIGN KEY (printer_id) REFERENCES printers(id),
|
||||
FOREIGN KEY (owner_id) REFERENCES users(id)
|
||||
)
|
||||
""")
|
||||
|
||||
# Daten zurückkopieren (title -> name)
|
||||
cursor.execute("""
|
||||
INSERT INTO jobs (
|
||||
id, name, description, user_id, printer_id, start_at, end_at,
|
||||
actual_end_time, status, created_at, notes, material_used,
|
||||
file_path, owner_id, duration_minutes
|
||||
)
|
||||
SELECT
|
||||
id, title, description, user_id, printer_id, start_at, end_at,
|
||||
actual_end_time, status, created_at, notes, material_used,
|
||||
file_path, owner_id, COALESCE(duration_minutes, 60)
|
||||
FROM jobs_backup
|
||||
""")
|
||||
|
||||
# Backup-Tabelle löschen
|
||||
cursor.execute("DROP TABLE jobs_backup")
|
||||
print("✓ Jobs-Tabelle erfolgreich konvertiert")
|
||||
|
||||
except sqlite3.OperationalError as e:
|
||||
print(f"⚠ Fehler bei Job-Tabellen-Migration: {e}")
|
||||
|
||||
# Änderungen speichern
|
||||
conn.commit()
|
||||
print("\n✅ Datenbankmigration erfolgreich abgeschlossen!")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ Fehler bei der Migration: {e}")
|
||||
conn.rollback()
|
||||
return False
|
||||
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = migrate_database()
|
||||
if success:
|
||||
print("\nDie Datenbank wurde erfolgreich migriert.")
|
||||
print("Sie können nun die Anwendung starten: python3.11 app.py")
|
||||
else:
|
||||
print("\nMigration fehlgeschlagen. Bitte überprüfen Sie die Fehlermeldungen.")
|
Reference in New Issue
Block a user