Kein PW bei Export

Dieser Commit ist enthalten in:
Claude Project Manager
2025-11-16 22:57:59 +01:00
Ursprung 88dc8eea5e
Commit 03ca1c607f
7 geänderte Dateien mit 45 neuen und 328 gelöschten Zeilen

Datei anzeigen

@ -1,18 +1,16 @@
"""
Profil-Export-Service für Account-Daten
Exportiert Account-Profile in verschiedene Formate (CSV, TXT, PDF)
mit optionalem Passwortschutz.
Exportiert Account-Profile in verschiedene Formate (CSV, TXT, PDF).
"""
import os
import csv
import secrets
import string
import logging
from io import BytesIO, StringIO
from datetime import datetime
from typing import Dict, Any, List, Optional, Tuple
from typing import Dict, Any, List
from pathlib import Path
logger = logging.getLogger("profile_export_service")
@ -287,88 +285,6 @@ class ProfileExportService:
logger.error(f"Fehler beim PDF-Export: {e}")
raise
@staticmethod
def generate_password(length: int = 10) -> str:
"""
Generiert ein sicheres zufälliges Passwort.
Args:
length: Länge des Passworts (Standard: 10)
Returns:
Generiertes Passwort
"""
# Zeichensatz: Groß- und Kleinbuchstaben, Zahlen, Sonderzeichen
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
# Sicherstellen dass mindestens ein Zeichen von jedem Typ vorhanden ist
password_chars = [
secrets.choice(string.ascii_uppercase), # Mindestens ein Großbuchstabe
secrets.choice(string.ascii_lowercase), # Mindestens ein Kleinbuchstabe
secrets.choice(string.digits), # Mindestens eine Zahl
secrets.choice("!@#$%^&*") # Mindestens ein Sonderzeichen
]
# Rest auffüllen
for _ in range(length - 4):
password_chars.append(secrets.choice(alphabet))
# Mischen für Zufälligkeit
secrets.SystemRandom().shuffle(password_chars)
password = ''.join(password_chars)
logger.info("Passwort generiert")
return password
@staticmethod
def create_protected_zip(files_dict: Dict[str, bytes], password: str) -> bytes:
"""
Erstellt eine passwortgeschützte ZIP-Datei.
Args:
files_dict: Dictionary mit {filename: content} Paaren
password: Passwort für die ZIP-Datei
Returns:
ZIP-Daten als bytes
"""
try:
import pyzipper
# ZIP-Buffer erstellen
buffer = BytesIO()
# ZIP mit AES-Verschlüsselung erstellen
with pyzipper.AESZipFile(
buffer,
'w',
compression=pyzipper.ZIP_DEFLATED,
encryption=pyzipper.WZ_AES
) as zf:
# Passwort setzen
zf.setpassword(password.encode('utf-8'))
# Dateien hinzufügen
for filename, content in files_dict.items():
zf.writestr(filename, content)
# Buffer-Wert holen
zip_content = buffer.getvalue()
buffer.close()
logger.info(f"Passwortgeschützte ZIP erstellt mit {len(files_dict)} Dateien")
return zip_content
except ImportError as e:
logger.error(f"pyzipper nicht installiert: {e}")
raise Exception(
"ZIP mit Passwortschutz erfordert 'pyzipper' Library. "
"Bitte installieren Sie: pip install pyzipper"
)
except Exception as e:
logger.error(f"Fehler beim Erstellen der geschützten ZIP: {e}")
raise
@staticmethod
def generate_filename(
account_data: Dict[str, Any],
@ -427,19 +343,17 @@ class ProfileExportService:
account_data: Dict[str, Any],
formats: List[str],
password_protect: bool = False
) -> Tuple[Dict[str, bytes], Optional[str]]:
) -> Dict[str, bytes]:
"""
Exportiert Account-Daten in angegebene Formate.
Args:
account_data: Account-Daten zum Exportieren
formats: Liste von Formaten ["csv", "txt", "pdf"]
password_protect: Ob Dateien passwortgeschützt werden sollen
password_protect: Wird ignoriert (für Rückwärtskompatibilität)
Returns:
Tuple von (files_dict, password)
- files_dict: {filename: content} für alle Formate
- password: Generiertes Passwort (None wenn nicht geschützt)
Dict mit {filename: content} für alle Formate
"""
files_dict = {}
@ -464,16 +378,4 @@ class ProfileExportService:
else:
logger.warning(f"Unbekanntes Format ignoriert: {fmt}")
# Passwortschutz wenn gewünscht
password = None
if password_protect and files_dict:
password = ProfileExportService.generate_password()
# Alle Dateien in ZIP packen
zip_filename = ProfileExportService.generate_filename(account_data, "zip")
zip_content = ProfileExportService.create_protected_zip(files_dict, password)
# Nur ZIP zurückgeben
files_dict = {zip_filename: zip_content}
return files_dict, password
return files_dict