manage-your-printer/utils/offline_config.py
2025-06-04 10:03:22 +02:00

229 lines
7.0 KiB
Python

"""
Offline-Konfiguration für MYP-System
===================================
Konfiguriert das System für den Offline-Betrieb ohne Internetverbindung.
Stellt Fallback-Lösungen für internetabhängige Funktionen bereit.
"""
import os
import logging
from typing import Dict, List, Optional
from utils.logging_config import get_logger
logger = get_logger("offline_config")
# ===== OFFLINE-MODUS KONFIGURATION =====
OFFLINE_MODE = True # Produktionseinstellung - System läuft offline
# ===== OFFLINE-KOMPATIBILITÄT PRÜFUNGEN =====
def check_internet_connectivity() -> bool:
"""
Prüft ob eine Internetverbindung verfügbar ist.
Im Offline-Modus gibt immer False zurück.
Returns:
bool: True wenn Internet verfügbar, False im Offline-Modus
"""
if OFFLINE_MODE:
return False
# In einem echten Online-Modus könnte hier eine echte Prüfung stehen
try:
import socket
socket.create_connection(("8.8.8.8", 53), timeout=3)
return True
except OSError:
return False
def is_oauth_available() -> bool:
"""
Prüft ob OAuth-Funktionalität verfügbar ist.
Returns:
bool: False im Offline-Modus
"""
return not OFFLINE_MODE and check_internet_connectivity()
def is_email_sending_available() -> bool:
"""
Prüft ob E-Mail-Versand verfügbar ist.
Returns:
bool: False im Offline-Modus (nur Logging)
"""
return not OFFLINE_MODE and check_internet_connectivity()
def is_cdn_available() -> bool:
"""
Prüft ob CDN-Links verfügbar sind.
Returns:
bool: False im Offline-Modus (lokale Fallbacks verwenden)
"""
return not OFFLINE_MODE and check_internet_connectivity()
# ===== CDN FALLBACK-KONFIGURATION =====
CDN_FALLBACKS = {
# Chart.js CDN -> Lokale Datei
"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.0/chart.min.js": "/static/js/charts/chart.min.js",
"https://cdn.jsdelivr.net/npm/chart.js": "/static/js/charts/chart.min.js",
# FontAwesome (bereits lokal verfügbar)
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css": "/static/fontawesome/css/all.min.css",
# Weitere CDN-Fallbacks können hier hinzugefügt werden
}
def get_local_asset_path(cdn_url: str) -> Optional[str]:
"""
Gibt den lokalen Pfad für eine CDN-URL zurück.
Args:
cdn_url: URL des CDN-Assets
Returns:
str: Lokaler Pfad oder None wenn kein Fallback verfügbar
"""
return CDN_FALLBACKS.get(cdn_url)
def replace_cdn_links(html_content: str) -> str:
"""
Ersetzt CDN-Links durch lokale Fallbacks im HTML-Inhalt.
Args:
html_content: HTML-Inhalt mit CDN-Links
Returns:
str: HTML-Inhalt mit lokalen Links
"""
if not OFFLINE_MODE:
return html_content
modified_content = html_content
for cdn_url, local_path in CDN_FALLBACKS.items():
if cdn_url in modified_content:
modified_content = modified_content.replace(cdn_url, local_path)
logger.info(f"🔄 CDN-Link ersetzt: {cdn_url} -> {local_path}")
return modified_content
# ===== SECURITY POLICY ANPASSUNGEN =====
def get_offline_csp_policy() -> Dict[str, List[str]]:
"""
Gibt CSP-Policy für Offline-Modus zurück.
Entfernt externe CDN-Domains aus der Policy.
Returns:
Dict: CSP-Policy ohne externe Domains
"""
if not OFFLINE_MODE:
# Online-Modus: Originale Policy mit CDNs
return {
"script-src": [
"'self'",
"'unsafe-inline'",
"'unsafe-eval'",
"https://cdn.jsdelivr.net",
"https://unpkg.com",
"https://cdnjs.cloudflare.com"
],
"style-src": [
"'self'",
"'unsafe-inline'",
"https://fonts.googleapis.com",
"https://cdn.jsdelivr.net"
],
"font-src": [
"'self'",
"https://fonts.gstatic.com"
]
}
else:
# Offline-Modus: Nur lokale Ressourcen
return {
"script-src": [
"'self'",
"'unsafe-inline'",
"'unsafe-eval'"
],
"style-src": [
"'self'",
"'unsafe-inline'"
],
"font-src": [
"'self'"
],
"img-src": [
"'self'",
"data:"
]
}
# ===== OFFLINE-MODUS HILFSFUNKTIONEN =====
def log_offline_mode_status():
"""Loggt den aktuellen Offline-Modus Status."""
if OFFLINE_MODE:
logger.info("🌐 System läuft im OFFLINE-MODUS")
logger.info(" ❌ OAuth deaktiviert")
logger.info(" ❌ E-Mail-Versand deaktiviert (nur Logging)")
logger.info(" ❌ CDN-Links werden durch lokale Dateien ersetzt")
logger.info(" ✅ Alle Kernfunktionen verfügbar")
else:
logger.info("🌐 System läuft im ONLINE-MODUS")
logger.info(" ✅ OAuth verfügbar")
logger.info(" ✅ E-Mail-Versand verfügbar")
logger.info(" ✅ CDN-Links verfügbar")
def get_feature_availability() -> Dict[str, bool]:
"""
Gibt die Verfügbarkeit verschiedener Features zurück.
Returns:
Dict: Feature-Verfügbarkeit
"""
return {
"oauth": is_oauth_available(),
"email_sending": is_email_sending_available(),
"cdn_resources": is_cdn_available(),
"offline_mode": OFFLINE_MODE,
"core_functionality": True, # Kernfunktionen immer verfügbar
"printer_control": True, # Drucker-Steuerung immer verfügbar
"job_management": True, # Job-Verwaltung immer verfügbar
"user_management": True # Benutzer-Verwaltung immer verfügbar
}
# ===== STARTUP-FUNKTIONEN =====
def initialize_offline_mode():
"""Initialisiert den Offline-Modus beim System-Start."""
log_offline_mode_status()
if OFFLINE_MODE:
logger.info("🔧 Initialisiere Offline-Modus-Anpassungen...")
# Prüfe ob lokale Chart.js verfügbar ist
chart_js_path = "static/js/charts/chart.min.js"
if not os.path.exists(chart_js_path):
logger.warning(f"⚠️ Lokale Chart.js nicht gefunden: {chart_js_path}")
logger.warning(" Diagramme könnten nicht funktionieren")
else:
logger.info(f"✅ Lokale Chart.js gefunden: {chart_js_path}")
# Prüfe weitere lokale Assets
fontawesome_path = "static/fontawesome/css/all.min.css"
if not os.path.exists(fontawesome_path):
logger.warning(f"⚠️ Lokale FontAwesome nicht gefunden: {fontawesome_path}")
else:
logger.info(f"✅ Lokale FontAwesome gefunden: {fontawesome_path}")
logger.info("✅ Offline-Modus erfolgreich initialisiert")
# Beim Import automatisch initialisieren
initialize_offline_mode()