"feat: Implement printer management

This commit is contained in:
Till Tomczak 2025-05-26 12:24:43 +02:00
parent 4282b52a3b
commit 57e306db08
11 changed files with 824 additions and 703 deletions

View File

@ -1923,154 +1923,4 @@ def validate_ssl_certificate():
except Exception as e: except Exception as e:
app_logger.error(f"Fehler bei der SSL-Validierung: {e}") app_logger.error(f"Fehler bei der SSL-Validierung: {e}")
return jsonify({"error": f"Fehler bei der Validierung: {str(e)}"}), 500
@login_required
def get_ssl_info():
"""Gibt Informationen über das aktuelle SSL-Zertifikat zurück."""
if not current_user.is_admin:
return jsonify({"error": "Nur Administratoren können SSL-Informationen abrufen"}), 403
try:
from utils.ssl_manager import ssl_manager
cert_info = ssl_manager.get_certificate_info()
if not cert_info:
return jsonify({
"exists": False,
"message": "Kein SSL-Zertifikat gefunden"
})
return jsonify({
"exists": True,
"certificate": cert_info,
"paths": {
"cert": ssl_manager.cert_path,
"key": ssl_manager.key_path
}
})
except Exception as e:
ssl_logger.error(f"Fehler beim Abrufen der SSL-Informationen: {e}")
return jsonify({"error": f"Fehler beim Abrufen der SSL-Informationen: {str(e)}"}), 500
@app.route("/api/ssl/generate", methods=["POST"])
@login_required
def generate_ssl_certificate():
"""Generiert ein neues SSL-Zertifikat."""
if not current_user.is_admin:
return jsonify({"error": "Nur Administratoren können SSL-Zertifikate generieren"}), 403
try:
from utils.ssl_manager import ssl_manager
# Parameter aus Request extrahieren
data = request.json or {}
key_size = data.get("key_size", 4096)
validity_days = data.get("validity_days", 365)
# Zertifikat generieren
success = ssl_manager.generate_mercedes_certificate(key_size, validity_days)
if success:
cert_info = ssl_manager.get_certificate_info()
ssl_logger.info(f"SSL-Zertifikat von {current_user.username} generiert")
return jsonify({
"success": True,
"message": "SSL-Zertifikat erfolgreich generiert",
"certificate": cert_info
})
else:
return jsonify({
"success": False,
"error": "Fehler beim Generieren des SSL-Zertifikats"
}), 500
except Exception as e:
ssl_logger.error(f"Fehler beim Generieren des SSL-Zertifikats: {e}")
return jsonify({"error": f"Fehler beim Generieren: {str(e)}"}), 500
@app.route("/api/ssl/install", methods=["POST"])
@login_required
def install_ssl_certificate():
"""Installiert das SSL-Zertifikat im System."""
if not current_user.is_admin:
return jsonify({"error": "Nur Administratoren können SSL-Zertifikate installieren"}), 403
try:
from utils.ssl_manager import ssl_manager
success = ssl_manager.install_system_certificate()
if success:
ssl_logger.info(f"SSL-Zertifikat von {current_user.username} im System installiert")
return jsonify({
"success": True,
"message": "SSL-Zertifikat erfolgreich im System installiert"
})
else:
return jsonify({
"success": False,
"error": "Fehler bei der Installation des SSL-Zertifikats im System"
}), 500
except Exception as e:
ssl_logger.error(f"Fehler bei der SSL-Installation: {e}")
return jsonify({"error": f"Fehler bei der Installation: {str(e)}"}), 500
@app.route("/api/ssl/copy-raspberry", methods=["POST"])
@login_required
def copy_ssl_to_raspberry():
"""Kopiert das SSL-Zertifikat auf den Raspberry Pi."""
if not current_user.is_admin:
return jsonify({"error": "Nur Administratoren können SSL-Zertifikate kopieren"}), 403
try:
from utils.ssl_manager import ssl_manager
# Parameter aus Request extrahieren
data = request.json or {}
host = data.get("host", "raspberrypi")
user = data.get("user", "pi")
dest = data.get("dest", "/home/pi/myp/ssl")
success = ssl_manager.copy_to_raspberry(host, user, dest)
if success:
ssl_logger.info(f"SSL-Zertifikat von {current_user.username} auf Raspberry Pi kopiert")
return jsonify({
"success": True,
"message": f"SSL-Zertifikat erfolgreich auf {host} kopiert"
})
else:
return jsonify({
"success": False,
"error": "Fehler beim Kopieren des SSL-Zertifikats auf den Raspberry Pi"
}), 500
except Exception as e:
ssl_logger.error(f"Fehler beim Kopieren auf Raspberry Pi: {e}")
return jsonify({"error": f"Fehler beim Kopieren: {str(e)}"}), 500
@app.route("/api/ssl/validate", methods=["GET"])
@login_required
def validate_ssl_certificate():
"""Validiert das aktuelle SSL-Zertifikat."""
if not current_user.is_admin:
return jsonify({"error": "Nur Administratoren können SSL-Zertifikate validieren"}), 403
try:
from utils.ssl_manager import ssl_manager
is_valid = ssl_manager.is_certificate_valid()
cert_info = ssl_manager.get_certificate_info()
return jsonify({
"valid": is_valid,
"certificate": cert_info,
"message": "Zertifikat ist gültig" if is_valid else "Zertifikat ist ungültig oder läuft bald ab"
})
except Exception as e:
ssl_logger.error(f"Fehler bei der SSL-Validierung: {e}")
return jsonify({"error": f"Fehler bei der Validierung: {str(e)}"}), 500 return jsonify({"error": f"Fehler bei der Validierung: {str(e)}"}), 500

View File

@ -0,0 +1,110 @@
#!/usr/bin/env python3
"""
Skript zur Bereinigung der Drucker-Datenbank und Hinzufügung der korrekten hardkodierten Drucker.
"""
import sys
import os
sys.path.append('.')
from config.settings import PRINTERS
from database.db_manager import DatabaseManager
from models import Printer
from datetime import datetime
def clean_and_add_printers():
"""Bereinigt die Drucker-Datenbank und fügt die korrekten hardkodierten Drucker hinzu."""
print("=== Drucker-Datenbank bereinigen und neu erstellen ===")
print(f"Hardkodierte Drucker: {len(PRINTERS)}")
try:
db = DatabaseManager()
session = db.get_session()
# Alle existierenden Drucker löschen
existing_printers = session.query(Printer).all()
print(f"Lösche {len(existing_printers)} existierende Drucker...")
for printer in existing_printers:
session.delete(printer)
session.commit()
print("✅ Alle alten Drucker gelöscht")
# Neue Drucker hinzufügen
added_count = 0
for printer_name, config in PRINTERS.items():
# Neuen Drucker erstellen
new_printer = Printer(
name=printer_name,
model="P115", # Standard-Modell
location="Labor", # Standard-Standort
ip_address=config["ip"],
mac_address=f"98:25:4A:E1:{printer_name[-1]}0:0{printer_name[-1]}", # Dummy MAC
plug_ip=config["ip"],
plug_username="admin",
plug_password="admin",
status="available", # Verfügbar, da in Konfiguration
active=True,
created_at=datetime.now()
)
session.add(new_printer)
print(f"{printer_name}: Hinzugefügt (IP: {config['ip']})")
added_count += 1
# Änderungen speichern
session.commit()
session.close()
print(f"\n{added_count} neue Drucker hinzugefügt")
print("Drucker-Datenbank erfolgreich bereinigt und neu erstellt!")
except Exception as e:
print(f"❌ Fehler beim Bereinigen: {e}")
if 'session' in locals():
session.rollback()
session.close()
def list_final_printers():
"""Zeigt die finalen Drucker in der Datenbank an."""
print("\n=== Finale Drucker-Liste ===")
try:
db = DatabaseManager()
session = db.get_session()
printers = session.query(Printer).all()
if not printers:
print("Keine Drucker in der Datenbank gefunden.")
return
print(f"{'ID':<5} {'Name':<15} {'Status':<12} {'IP-Adresse':<15} {'Aktiv':<8}")
print("-" * 60)
for printer in printers:
active_str = "" if printer.active else ""
print(f"{printer.id:<5} {printer.name:<15} {printer.status:<12} {printer.ip_address:<15} {active_str:<8}")
session.close()
print(f"\nGesamt: {len(printers)} Drucker")
except Exception as e:
print(f"❌ Fehler beim Abrufen: {e}")
if 'session' in locals():
session.close()
if __name__ == "__main__":
print("Drucker-Datenbank Bereinigung und Neuerstellung")
print("=" * 50)
# Datenbank bereinigen und neue Drucker hinzufügen
clean_and_add_printers()
# Finale Liste anzeigen
list_final_printers()

View File

@ -128,95 +128,22 @@ def get_ssl_context():
def create_simple_ssl_cert(): def create_simple_ssl_cert():
""" """
Erstellt ein einfaches selbstsigniertes Zertifikat mit Python. Erstellt ein Mercedes-Benz SSL-Zertifikat mit dem neuen SSL-Manager.
Dies ist ein Fallback, falls OpenSSL nicht verfügbar ist.
""" """
try: try:
import datetime # Verwende den neuen SSL-Manager
import socket from utils.ssl_manager import ssl_manager
from cryptography import x509 success = ssl_manager.generate_mercedes_certificate()
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption
# Generiere privaten Schlüssel
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=4096, # Stärkere Schlüsselgröße
)
# Schreibe privaten Schlüssel
with open(SSL_KEY_PATH, "wb") as f:
f.write(private_key.private_bytes(
encoding=Encoding.PEM,
format=PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=NoEncryption()
))
# Aktuelles Datum und Ablaufdatum berechnen
now = datetime.datetime.now()
valid_until = now + datetime.timedelta(days=3650) # 10 Jahre gültig
# Erstelle Zertifikat mit erweiterten Attributen
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, SSL_HOSTNAME),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Mercedes-Benz AG"),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "Werk 040 Berlin"),
x509.NameAttribute(NameOID.COUNTRY_NAME, "DE"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Berlin"),
x509.NameAttribute(NameOID.LOCALITY_NAME, "Berlin")
])
cert = x509.CertificateBuilder().subject_name(
subject
).issuer_name(
issuer
).public_key(
private_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
now
).not_valid_after(
valid_until
).add_extension(
x509.SubjectAlternativeName([
x509.DNSName(SSL_HOSTNAME),
x509.DNSName("localhost"),
x509.IPAddress(socket.inet_aton("127.0.0.1"))
]),
critical=False,
).add_extension(
x509.BasicConstraints(ca=True, path_length=None), critical=True
).add_extension(
x509.KeyUsage(
digital_signature=True,
content_commitment=False,
key_encipherment=True,
data_encipherment=False,
key_agreement=False,
key_cert_sign=True,
crl_sign=True,
encipher_only=False,
decipher_only=False
), critical=True
).add_extension(
x509.ExtendedKeyUsage([
x509.oid.ExtendedKeyUsageOID.SERVER_AUTH,
x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH
]), critical=False
).sign(private_key, hashes.SHA256())
# Schreibe Zertifikat
with open(SSL_CERT_PATH, "wb") as f:
f.write(cert.public_bytes(Encoding.PEM))
print(f"Verbessertes selbstsigniertes Zertifikat erstellt: {SSL_CERT_PATH}") if success:
print(f"Gültig bis: {valid_until.strftime('%d.%m.%Y')}") print(f"Mercedes-Benz SSL-Zertifikat erfolgreich erstellt: {SSL_CERT_PATH}")
return True
except ImportError: else:
print("Konnte keine SSL-Zertifikate erstellen: cryptography-Paket nicht installiert") print("Fehler beim Erstellen des Mercedes-Benz SSL-Zertifikats")
return None
except ImportError as e:
print(f"SSL-Manager nicht verfügbar: {e}")
return None return None
except Exception as e: except Exception as e:
print(f"Fehler beim Erstellen der SSL-Zertifikate: {e}") print(f"Fehler beim Erstellen der SSL-Zertifikate: {e}")

View File

@ -86,8 +86,8 @@ if __name__ == "__main__":
import argparse import argparse
parser = argparse.ArgumentParser(description="Erstellt selbstsignierte SSL-Zertifikate für die lokale Entwicklung") parser = argparse.ArgumentParser(description="Erstellt selbstsignierte SSL-Zertifikate für die lokale Entwicklung")
parser.add_argument("-c", "--cert", default="instance/ssl/myp.crt", help="Pfad zur Zertifikatsdatei") parser.add_argument("-c", "--cert", default="../certs/myp.crt", help="Pfad zur Zertifikatsdatei")
parser.add_argument("-k", "--key", default="instance/ssl/myp.key", help="Pfad zur Schlüsseldatei") parser.add_argument("-k", "--key", default="../certs/myp.key", help="Pfad zur Schlüsseldatei")
parser.add_argument("-n", "--hostname", default="localhost", help="Hostname für das Zertifikat") parser.add_argument("-n", "--hostname", default="localhost", help="Hostname für das Zertifikat")
args = parser.parse_args() args = parser.parse_args()

Binary file not shown.

View File

@ -416,6 +416,12 @@
</svg> </svg>
Logs Logs
</a> </a>
<a href="{{ url_for('admin_page', tab='ssl') }}" class="tab-modern {{ 'active' if active_tab == 'ssl' else '' }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
</svg>
SSL
</a>
</div> </div>
<!-- Tab Content --> <!-- Tab Content -->
@ -658,11 +664,270 @@
</div> </div>
</div> </div>
</div> </div>
{% endif %}
<!-- SSL Tab -->
{% if active_tab == 'ssl' %}
<div class="content-card-modern">
<div class="flex flex-col md:flex-row md:justify-between md:items-center mb-8 gap-4">
<h3 class="text-3xl font-bold text-slate-900 dark:text-white">SSL-Zertifikatsverwaltung</h3>
<button onclick="loadSSLInfo()" class="btn-modern">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
</svg>
Aktualisieren
</button>
</div>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!-- Zertifikatsinformationen -->
<div class="form-modern">
<h4 class="text-xl font-semibold text-slate-900 dark:text-white mb-6">Aktuelles Zertifikat</h4>
<div id="ssl-info-container">
<div class="text-center py-8">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto"></div>
<p class="mt-2 text-slate-600 dark:text-slate-400">Lade Zertifikatsinformationen...</p>
</div>
</div>
</div>
<!-- SSL-Aktionen -->
<div class="form-modern">
<h4 class="text-xl font-semibold text-slate-900 dark:text-white mb-6">Zertifikatsverwaltung</h4>
<div class="space-y-4">
<button onclick="generateSSLCertificate()" class="btn-modern w-full justify-center">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
Neues Zertifikat generieren
</button>
<button onclick="installSSLCertificate()" class="btn-success-modern w-full justify-center">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
Im System installieren
</button>
<button onclick="copyToRaspberry()" class="btn-modern w-full justify-center">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
Auf Raspberry Pi kopieren
</button>
<button onclick="validateSSLCertificate()" class="btn-modern w-full justify-center">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
Zertifikat validieren
</button>
</div>
</div>
</div>
<!-- Erweiterte Optionen -->
<div class="form-modern mt-8">
<h4 class="text-xl font-semibold text-slate-900 dark:text-white mb-6">Erweiterte Optionen</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label for="ssl-key-size" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Schlüsselgröße (Bits)</label>
<select id="ssl-key-size" class="input-modern w-full">
<option value="2048">2048 Bit</option>
<option value="4096" selected>4096 Bit (Empfohlen)</option>
<option value="8192">8192 Bit</option>
</select>
</div>
<div>
<label for="ssl-validity" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Gültigkeitsdauer (Tage)</label>
<input type="number" id="ssl-validity" value="365" min="30" max="3650" class="input-modern w-full">
</div>
</div>
</div>
</div>
{% endif %} {% endif %}
<!-- Weitere Tabs können hier hinzugefügt werden --> <!-- Weitere Tabs können hier hinzugefügt werden -->
</div> </div>
</div> </div>
<script>
// SSL-Verwaltungsfunktionen
async function loadSSLInfo() {
const container = document.getElementById('ssl-info-container');
container.innerHTML = `
<div class="text-center py-8">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto"></div>
<p class="mt-2 text-slate-600 dark:text-slate-400">Lade Zertifikatsinformationen...</p>
</div>
`;
try {
const response = await fetch('/api/ssl/info');
const data = await response.json();
if (data.exists) {
const cert = data.certificate;
const isExpired = cert.is_expired;
const daysUntilExpiry = cert.days_until_expiry;
container.innerHTML = `
<div class="space-y-4">
<div class="flex items-center justify-between p-4 bg-white dark:bg-slate-700 rounded-lg">
<span class="font-medium text-slate-900 dark:text-white">Status</span>
<span class="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium ${isExpired ? 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200' : daysUntilExpiry < 30 ? 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200' : 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'}">
${isExpired ? 'Abgelaufen' : daysUntilExpiry < 30 ? 'Läuft bald ab' : 'Gültig'}
</span>
</div>
<div class="p-4 bg-white dark:bg-slate-700 rounded-lg">
<div class="text-sm text-slate-600 dark:text-slate-400 mb-1">Gültig bis</div>
<div class="font-medium text-slate-900 dark:text-white">${cert.not_valid_after}</div>
</div>
<div class="p-4 bg-white dark:bg-slate-700 rounded-lg">
<div class="text-sm text-slate-600 dark:text-slate-400 mb-1">Verbleibende Tage</div>
<div class="font-medium text-slate-900 dark:text-white">${daysUntilExpiry} Tage</div>
</div>
<div class="p-4 bg-white dark:bg-slate-700 rounded-lg">
<div class="text-sm text-slate-600 dark:text-slate-400 mb-1">Schlüsselgröße</div>
<div class="font-medium text-slate-900 dark:text-white">${cert.key_size || 'Unbekannt'} Bit</div>
</div>
<div class="p-4 bg-white dark:bg-slate-700 rounded-lg">
<div class="text-sm text-slate-600 dark:text-slate-400 mb-1">Fingerprint (SHA256)</div>
<div class="font-mono text-xs text-slate-900 dark:text-white break-all">${cert.fingerprint}</div>
</div>
</div>
`;
} else {
container.innerHTML = `
<div class="text-center py-8">
<svg class="w-16 h-16 text-slate-400 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
</svg>
<p class="text-slate-600 dark:text-slate-400">Kein SSL-Zertifikat gefunden</p>
<p class="text-sm text-slate-500 dark:text-slate-500 mt-2">Generieren Sie ein neues Zertifikat</p>
</div>
`;
}
} catch (error) {
container.innerHTML = `
<div class="text-center py-8">
<svg class="w-16 h-16 text-red-400 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<p class="text-red-600 dark:text-red-400">Fehler beim Laden der Zertifikatsinformationen</p>
<p class="text-sm text-slate-500 dark:text-slate-500 mt-2">${error.message}</p>
</div>
`;
}
}
async function generateSSLCertificate() {
const keySize = document.getElementById('ssl-key-size').value;
const validity = document.getElementById('ssl-validity').value;
try {
const response = await fetch('/api/ssl/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
},
body: JSON.stringify({
key_size: parseInt(keySize),
validity_days: parseInt(validity)
})
});
const data = await response.json();
if (data.success) {
alert('SSL-Zertifikat erfolgreich generiert!');
loadSSLInfo();
} else {
alert('Fehler beim Generieren des SSL-Zertifikats: ' + data.error);
}
} catch (error) {
alert('Fehler beim Generieren des SSL-Zertifikats: ' + error.message);
}
}
async function installSSLCertificate() {
try {
const response = await fetch('/api/ssl/install', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
}
});
const data = await response.json();
if (data.success) {
alert('SSL-Zertifikat erfolgreich im System installiert!');
} else {
alert('Fehler bei der Installation: ' + data.error);
}
} catch (error) {
alert('Fehler bei der Installation: ' + error.message);
}
}
async function copyToRaspberry() {
const host = prompt('Raspberry Pi Hostname:', 'raspberrypi');
if (!host) return;
const user = prompt('Benutzername:', 'pi');
if (!user) return;
try {
const response = await fetch('/api/ssl/copy-raspberry', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
},
body: JSON.stringify({
host: host,
user: user
})
});
const data = await response.json();
if (data.success) {
alert('SSL-Zertifikat erfolgreich auf Raspberry Pi kopiert!');
} else {
alert('Fehler beim Kopieren: ' + data.error);
}
} catch (error) {
alert('Fehler beim Kopieren: ' + error.message);
}
}
async function validateSSLCertificate() {
try {
const response = await fetch('/api/ssl/validate');
const data = await response.json();
if (data.valid) {
alert('SSL-Zertifikat ist gültig!');
} else {
alert('SSL-Zertifikat ist ungültig oder läuft bald ab: ' + data.message);
}
} catch (error) {
alert('Fehler bei der Validierung: ' + error.message);
}
}
// SSL-Informationen beim Laden des SSL-Tabs laden
document.addEventListener('DOMContentLoaded', function() {
if (window.location.search.includes('tab=ssl')) {
loadSSLInfo();
}
});
</script>
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}

View File

@ -79,8 +79,8 @@ class SSLCertificateManager:
"""Entfernt alte Zertifikate und veraltete Verzeichnisse""" """Entfernt alte Zertifikate und veraltete Verzeichnisse"""
# Alte SSL-Verzeichnisse löschen # Alte SSL-Verzeichnisse löschen
old_ssl_dirs = [ old_ssl_dirs = [
os.path.join(os.path.dirname(self.certs_dir), "instance", "ssl"), os.path.join(os.path.dirname(os.path.dirname(self.certs_dir)), "app", "instance", "ssl"),
os.path.join(os.path.dirname(self.certs_dir), "ssl") os.path.join(os.path.dirname(os.path.dirname(self.certs_dir)), "app", "certs")
] ]
for old_dir in old_ssl_dirs: for old_dir in old_ssl_dirs:

View File

@ -1,171 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import datetime
import shutil
from pathlib import Path
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption
import ipaddress
def generate_mercedes_certificate():
"""
Generiert ein vollständiges Mercedes-Benz-Zertifikat
mit korrekten Metadaten und alternativen Namen.
"""
print("Generiere Mercedes-Benz SSL-Zertifikat...")
# Verzeichnispfade definieren und alte Zertifikate löschen
old_ssl_dir = "app/instance/ssl"
if os.path.exists(old_ssl_dir):
print(f"Lösche alten SSL-Ordner: {old_ssl_dir}")
try:
shutil.rmtree(old_ssl_dir)
except Exception as e:
print(f"Warnung: Konnte alten SSL-Ordner nicht löschen: {e}")
# Neues Zielverzeichnis
certs_dir = "app/certs"
os.makedirs(certs_dir, exist_ok=True)
# Pfade zu Zertifikat und Schlüssel
cert_path = os.path.join(certs_dir, "myp.crt")
key_path = os.path.join(certs_dir, "myp.key")
# Entferne alte Zertifikate, falls vorhanden
for path in [cert_path, key_path]:
if os.path.exists(path):
os.remove(path)
try:
# Privaten Schlüssel mit 4096 Bit generieren (sicherer)
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=4096,
)
# Aktuelles Datum und Ablaufdatum (1 Jahr gültig)
now = datetime.datetime.now()
valid_until = now + datetime.timedelta(days=365)
# Liste aller möglichen Hostnamen/IPs
hostnames = [
"localhost",
"raspberrypi",
"m040tbaraspi001",
"m040tbaraspi001.de040.corpintra.net",
"mbag.corpintra.net",
"mbag.mb.corpintra.net"
]
# IP-Adressen (als String, werden später konvertiert)
ip_addresses = [
"127.0.0.1",
"192.168.0.101",
"192.168.0.102",
"192.168.0.103",
"192.168.0.104",
"192.168.0.105",
"192.168.0.106"
]
# Erweiterte Zertifikatsattribute für Mercedes-Benz
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, "raspberrypi"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Mercedes-Benz AG"),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "Werk 040 Berlin"),
x509.NameAttribute(NameOID.LOCALITY_NAME, "Berlin"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Berlin"),
x509.NameAttribute(NameOID.COUNTRY_NAME, "DE"),
x509.NameAttribute(NameOID.EMAIL_ADDRESS, "admin@mercedes-benz.com"),
])
# Subject Alternative Names (SAN) erstellen
san_list = []
for hostname in hostnames:
san_list.append(x509.DNSName(hostname))
# IP-Adressen hinzufügen
for ip in ip_addresses:
san_list.append(x509.IPAddress(ipaddress.IPv4Address(ip)))
# Zertifikat erstellen
cert = x509.CertificateBuilder().subject_name(
subject
).issuer_name(
issuer
).public_key(
private_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
now
).not_valid_after(
valid_until
).add_extension(
x509.SubjectAlternativeName(san_list),
critical=False,
).add_extension(
x509.BasicConstraints(ca=True, path_length=None), critical=True
).add_extension(
x509.KeyUsage(
digital_signature=True,
content_commitment=False,
key_encipherment=True,
data_encipherment=False,
key_agreement=False,
key_cert_sign=True,
crl_sign=True,
encipher_only=False,
decipher_only=False
), critical=True
).add_extension(
x509.ExtendedKeyUsage([
x509.oid.ExtendedKeyUsageOID.SERVER_AUTH,
x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH,
x509.oid.ExtendedKeyUsageOID.CODE_SIGNING
]), critical=False
).sign(private_key, hashes.SHA256())
# Zertifikat und Schlüssel speichern
with open(key_path, "wb") as f:
f.write(private_key.private_bytes(
encoding=Encoding.PEM,
format=PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=NoEncryption()
))
with open(cert_path, "wb") as f:
f.write(cert.public_bytes(Encoding.PEM))
print(f"Mercedes-Benz SSL-Zertifikat wurde erfolgreich erstellt:")
print(f"- Zertifikat: {os.path.abspath(cert_path)}")
print(f"- Schlüssel: {os.path.abspath(key_path)}")
print(f"- Gültig bis: {valid_until.strftime('%d.%m.%Y')}")
print(f"- Hostnamen: {', '.join(hostnames)}")
print(f"- IP-Adressen: {', '.join(ip_addresses)}")
# Kopieren des Zertifikats in das Frontend-Verzeichnis
frontend_ssl_dir = "../frontend/ssl"
os.makedirs(frontend_ssl_dir, exist_ok=True)
shutil.copy2(cert_path, os.path.join(frontend_ssl_dir, "myp.crt"))
shutil.copy2(key_path, os.path.join(frontend_ssl_dir, "myp.key"))
print(f"Zertifikate wurden in das Frontend-Verzeichnis kopiert: {os.path.abspath(frontend_ssl_dir)}")
return True
except Exception as e:
print(f"Fehler beim Erstellen des Mercedes-Benz SSL-Zertifikats: {e}")
return False
if __name__ == "__main__":
success = generate_mercedes_certificate()
if success:
print("Mercedes-Benz SSL-Zertifikatserstellung erfolgreich abgeschlossen.")
else:
print("Fehler bei der Zertifikatserstellung!")
exit(1)

View File

@ -1,261 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import datetime
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption
import ipaddress
import argparse
def generate_ssl_certificate():
"""
Generiert ein verbessertes SSL-Zertifikat für die MYP-Anwendung
mit korrekten Metadaten und alternativen Namen.
"""
print("Generiere verbessertes SSL-Zertifikat für die MYP-Anwendung...")
# Verzeichnispfade definieren
ssl_dir = "app/instance/ssl"
ssl_cert_path = os.path.join(ssl_dir, "myp.crt")
ssl_key_path = os.path.join(ssl_dir, "myp.key")
# Verzeichnis erstellen, falls es nicht existiert
os.makedirs(ssl_dir, exist_ok=True)
try:
# Privaten Schlüssel mit 4096 Bit generieren (sicherer)
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=4096,
)
# Aktuelles Datum und Ablaufdatum (1 Jahr gültig)
now = datetime.datetime.now()
valid_until = now + datetime.timedelta(days=365)
# Liste aller möglichen Hostnamen/IPs
hostnames = [
"localhost",
"raspberrypi",
"m040tbaraspi001",
"m040tbaraspi001.de040.corpintra.net"
]
# IP-Adressen (als String, werden später konvertiert)
ip_addresses = [
"127.0.0.1",
"192.168.0.105"
]
# Erweiterte Zertifikatsattribute
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, "raspberrypi"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Mercedes-Benz AG"),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "Werk 040 Berlin"),
x509.NameAttribute(NameOID.COUNTRY_NAME, "DE"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Berlin"),
x509.NameAttribute(NameOID.LOCALITY_NAME, "Berlin")
])
# Subject Alternative Names (SAN) erstellen
san_list = []
for hostname in hostnames:
san_list.append(x509.DNSName(hostname))
# IP-Adressen hinzufügen
for ip in ip_addresses:
san_list.append(x509.IPAddress(ipaddress.IPv4Address(ip)))
# Zertifikat erstellen
cert = x509.CertificateBuilder().subject_name(
subject
).issuer_name(
issuer
).public_key(
private_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
now
).not_valid_after(
valid_until
).add_extension(
x509.SubjectAlternativeName(san_list),
critical=False,
).add_extension(
x509.BasicConstraints(ca=True, path_length=None), critical=True
).add_extension(
x509.KeyUsage(
digital_signature=True,
content_commitment=False,
key_encipherment=True,
data_encipherment=False,
key_agreement=False,
key_cert_sign=True,
crl_sign=True,
encipher_only=False,
decipher_only=False
), critical=True
).add_extension(
x509.ExtendedKeyUsage([
x509.oid.ExtendedKeyUsageOID.SERVER_AUTH,
x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH
]), critical=False
).sign(private_key, hashes.SHA256())
# Zertifikat und Schlüssel speichern
with open(ssl_key_path, "wb") as f:
f.write(private_key.private_bytes(
encoding=Encoding.PEM,
format=PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=NoEncryption()
))
with open(ssl_cert_path, "wb") as f:
f.write(cert.public_bytes(Encoding.PEM))
# Kopieren des Zertifikats in das Frontend-Verzeichnis
frontend_ssl_dir = "../frontend/ssl"
os.makedirs(frontend_ssl_dir, exist_ok=True)
import shutil
shutil.copy2(ssl_cert_path, os.path.join(frontend_ssl_dir, "myp.crt"))
shutil.copy2(ssl_key_path, os.path.join(frontend_ssl_dir, "myp.key"))
print(f"SSL-Zertifikat wurde erstellt:")
print(f"- Zertifikat: {ssl_cert_path}")
print(f"- Schlüssel: {ssl_key_path}")
print(f"- Kopiert nach: {frontend_ssl_dir}")
print(f"- Gültig bis: {valid_until.strftime('%d.%m.%Y')}")
print(f"- Hostnamen: {', '.join(hostnames)}")
print(f"- IP-Adressen: {', '.join(ip_addresses)}")
return True
except Exception as e:
print(f"Fehler beim Erstellen des SSL-Zertifikats: {e}")
return False
def install_certificate_system():
"""
Installiert das Zertifikat im System-Zertifikatsspeicher (Windows).
Nur für Windows-Systeme.
"""
import platform
if platform.system() != "Windows":
print("Diese Funktion ist nur unter Windows verfügbar.")
return False
try:
import subprocess
import os
ssl_cert_path = os.path.abspath(os.path.join("app", "instance", "ssl", "myp.crt"))
# Prüfen, ob Datei existiert
if not os.path.exists(ssl_cert_path):
print(f"Zertifikat nicht gefunden unter: {ssl_cert_path}")
# Alternativen Pfad versuchen
alt_path = os.path.abspath(os.path.join("backend", "app", "instance", "ssl", "myp.crt"))
if os.path.exists(alt_path):
ssl_cert_path = alt_path
print(f"Verwende alternativen Pfad: {ssl_cert_path}")
else:
print("Zertifikat konnte nicht gefunden werden.")
return False
# Befehle zum Installieren des Zertifikats im Windows-Zertifikatsspeicher
commands = [
["certutil", "-addstore", "-f", "ROOT", ssl_cert_path],
["certutil", "-addstore", "-f", "CA", ssl_cert_path],
["certutil", "-addstore", "-f", "MY", ssl_cert_path]
]
for cmd in commands:
subprocess.run(cmd, check=True, capture_output=True)
print("Zertifikat wurde erfolgreich im System-Zertifikatsspeicher installiert.")
return True
except Exception as e:
print(f"Fehler bei der Installation des Zertifikats im System: {e}")
return False
def copy_to_raspberry():
"""
Kopiert das Zertifikat auf den Raspberry Pi.
Erfordert SSH-Zugriff auf den Raspberry Pi.
"""
try:
import subprocess
ssl_cert_path = os.path.abspath("app/instance/ssl/myp.crt")
ssl_key_path = os.path.abspath("app/instance/ssl/myp.key")
# Raspberry Pi-Zugangsdaten
raspberry_host = "raspberrypi"
raspberry_user = "pi"
raspberry_dest = "/home/pi/myp/ssl"
# Befehle zum Kopieren der Dateien auf den Raspberry Pi
scp_commands = [
["scp", ssl_cert_path, f"{raspberry_user}@{raspberry_host}:{raspberry_dest}/myp.crt"],
["scp", ssl_key_path, f"{raspberry_user}@{raspberry_host}:{raspberry_dest}/myp.key"]
]
# SSH-Befehl zum Erstellen des Verzeichnisses auf dem Raspberry Pi
ssh_command = ["ssh", f"{raspberry_user}@{raspberry_host}", f"mkdir -p {raspberry_dest}"]
# Verzeichnis auf dem Raspberry Pi erstellen
print(f"Erstelle Verzeichnis auf dem Raspberry Pi: {raspberry_dest}")
subprocess.run(ssh_command, check=True)
# Dateien kopieren
for cmd in scp_commands:
print(f"Kopiere {cmd[1]} nach {cmd[2]}")
subprocess.run(cmd, check=True)
print(f"Zertifikate wurden erfolgreich auf den Raspberry Pi kopiert nach {raspberry_dest}")
# Berechtigungen setzen
chmod_command = ["ssh", f"{raspberry_user}@{raspberry_host}", f"chmod 600 {raspberry_dest}/myp.key"]
subprocess.run(chmod_command, check=True)
# Zertifikat im System-Zertifikatsspeicher installieren
install_command = ["ssh", f"{raspberry_user}@{raspberry_host}", f"sudo cp {raspberry_dest}/myp.crt /usr/local/share/ca-certificates/ && sudo update-ca-certificates"]
subprocess.run(install_command, check=True)
print("Zertifikat wurde erfolgreich auf dem Raspberry Pi installiert und registriert.")
return True
except Exception as e:
print(f"Fehler beim Kopieren des Zertifikats auf den Raspberry Pi: {e}")
return False
if __name__ == "__main__":
print("=== MYP SSL-Zertifikatsgenerator ===")
# Kommandozeilenargumente parsen
parser = argparse.ArgumentParser(description='MYP SSL-Zertifikatsgenerator')
parser.add_argument('--no-install', action='store_true', help='Zertifikat nicht im System installieren')
parser.add_argument('--no-raspberry', action='store_true', help='Zertifikat nicht auf den Raspberry Pi kopieren')
parser.add_argument('--quiet', action='store_true', help='Keine Benutzerinteraktion')
args = parser.parse_args()
# Zertifikat generieren
cert_generated = generate_ssl_certificate()
if not cert_generated:
print("Generierung des Zertifikats fehlgeschlagen.")
exit(1)
# System-Installation des Zertifikats
if not args.no_install:
if args.quiet or input("Möchten Sie das Zertifikat im System-Zertifikatsspeicher installieren? (j/n): ").lower() == 'j':
install_certificate_system()
# Kopieren auf Raspberry Pi
if not args.no_raspberry:
if args.quiet or input("Möchten Sie das Zertifikat auf den Raspberry Pi kopieren? (j/n): ").lower() == 'j':
copy_to_raspberry()
print("Vorgang abgeschlossen.")

View File

@ -28,8 +28,8 @@ if (!fs.existsSync(path.join(SSL_DIR, 'myp.crt')) || !fs.existsSync(path.join(SS
console.log('SSL-Zertifikate nicht gefunden. Prüfe Backend-Verzeichnis...'); console.log('SSL-Zertifikate nicht gefunden. Prüfe Backend-Verzeichnis...');
// Versuche, die Zertifikate aus dem Backend zu kopieren // Versuche, die Zertifikate aus dem Backend zu kopieren
const backendCertPath = path.join('..', 'backend', 'app', 'instance', 'ssl', 'myp.crt'); const backendCertPath = path.join('..', 'backend', 'certs', 'myp.crt');
const backendKeyPath = path.join('..', 'backend', 'app', 'instance', 'ssl', 'myp.key'); const backendKeyPath = path.join('..', 'backend', 'certs', 'myp.key');
if (fs.existsSync(backendCertPath) && fs.existsSync(backendKeyPath)) { if (fs.existsSync(backendCertPath) && fs.existsSync(backendKeyPath)) {
console.log('Zertifikate im Backend-Verzeichnis gefunden. Kopiere...'); console.log('Zertifikate im Backend-Verzeichnis gefunden. Kopiere...');

View File

@ -150,6 +150,14 @@ test_dependencies() {
all_installed=0 all_installed=0
fi fi
# curl
if check_command curl; then
echo -e "${GREEN}✓ cURL gefunden${NC}"
else
echo -e "${RED}✗ cURL nicht gefunden${NC}"
all_installed=0
fi
echo "" echo ""
if [ $all_installed -eq 1 ]; then if [ $all_installed -eq 1 ]; then
echo -e "${GREEN}✓ Alle Abhängigkeiten sind installiert!${NC}" echo -e "${GREEN}✓ Alle Abhängigkeiten sind installiert!${NC}"
@ -213,6 +221,388 @@ setup_hosts() {
read -p "Drücken Sie ENTER, um fortzufahren..." read -p "Drücken Sie ENTER, um fortzufahren..."
} }
test_backend_connection() {
show_header "Backend-Verbindung prüfen"
echo -e "${BLUE}Welches Backend möchten Sie testen?${NC}"
echo -e "${WHITE}1. Lokales Backend (localhost:443)${NC}"
echo -e "${WHITE}2. Raspberry Pi Backend (192.168.0.105:5000)${NC}"
echo -e "${WHITE}3. Benutzerdefinierte URL${NC}"
read -p "Wählen Sie eine Option (1-3, Standard: 1): " choice
backend_url="https://localhost:443"
backend_host="localhost"
case $choice in
2)
backend_url="http://192.168.0.105:5000"
backend_host="192.168.0.105"
;;
3)
read -p "Backend-URL eingeben (z.B. https://raspberrypi:443): " backend_url
backend_host=$(echo "$backend_url" | sed -E 's|https?://([^:/]+).*|\1|')
;;
*)
backend_url="https://localhost:443"
backend_host="localhost"
;;
esac
echo ""
echo -e "${BLUE}Teste Backend: $backend_url${NC}"
echo ""
# 1. Netzwerk-Konnektivität prüfen
echo -e "${BLUE}1. Prüfe Netzwerk-Konnektivität zu $backend_host...${NC}"
if ping -c 1 -W 3 "$backend_host" >/dev/null 2>&1; then
echo -e "${GREEN}✓ Ping zu $backend_host erfolgreich${NC}"
else
echo -e "${RED}✗ Ping zu $backend_host fehlgeschlagen${NC}"
fi
# 2. Backend-Service prüfen
echo -e "${BLUE}2. Prüfe Backend-Service...${NC}"
health_url="$backend_url/health"
if curl -f --connect-timeout 5 "$health_url" >/dev/null 2>&1; then
echo -e "${GREEN}✓ Backend-Health-Check erfolgreich${NC}"
elif curl -f --connect-timeout 5 "$backend_url" >/dev/null 2>&1; then
echo -e "${YELLOW}⚠ Backend erreichbar, aber kein Health-Endpoint${NC}"
else
echo -e "${RED}✗ Backend-Service nicht erreichbar${NC}"
fi
# 3. API-Endpunkte prüfen
echo -e "${BLUE}3. Prüfe Backend-API-Endpunkte...${NC}"
for endpoint in "printers" "jobs" "users"; do
api_url="$backend_url/api/$endpoint"
if curl -f --connect-timeout 5 "$api_url" >/dev/null 2>&1; then
echo -e "${GREEN}✓ API-Endpunkt /$endpoint erreichbar${NC}"
else
echo -e "${YELLOW}⚠ API-Endpunkt /$endpoint nicht erreichbar${NC}"
fi
done
# 4. Frontend-Konfiguration prüfen
echo -e "${BLUE}4. Prüfe Frontend-Konfigurationsdateien...${NC}"
env_local_path="frontend/.env.local"
if [ -f "$env_local_path" ]; then
if grep -q "NEXT_PUBLIC_API_URL" "$env_local_path"; then
echo -e "${GREEN}✓ .env.local gefunden und konfiguriert${NC}"
else
echo -e "${YELLOW}⚠ .env.local existiert, aber Backend-URL fehlt${NC}"
fi
else
echo -e "${YELLOW}⚠ .env.local nicht gefunden${NC}"
fi
echo ""
read -p "Möchten Sie die Frontend-Konfiguration für dieses Backend aktualisieren? (j/n): " update_config
if [ "$update_config" = "j" ]; then
setup_backend_url "$backend_url"
fi
echo ""
read -p "Drücken Sie ENTER, um fortzufahren..."
}
setup_backend_url() {
local backend_url="$1"
show_header "Backend-URL konfigurieren"
if [ -z "$backend_url" ]; then
echo -e "${BLUE}Verfügbare Backend-Konfigurationen:${NC}"
echo -e "${WHITE}1. Lokale Entwicklung (https://localhost:443)${NC}"
echo -e "${WHITE}2. Raspberry Pi (http://192.168.0.105:5000)${NC}"
echo -e "${WHITE}3. Benutzerdefinierte URL${NC}"
read -p "Wählen Sie eine Option (1-3, Standard: 1): " choice
case $choice in
2)
backend_url="http://192.168.0.105:5000"
;;
3)
read -p "Backend-URL eingeben (z.B. https://raspberrypi:443): " backend_url
;;
*)
backend_url="https://localhost:443"
;;
esac
fi
echo -e "${BLUE}Konfiguriere Frontend für Backend: $backend_url${NC}"
# .env.local erstellen/aktualisieren
env_local_path="frontend/.env.local"
backend_host=$(echo "$backend_url" | sed -E 's|https?://([^:/]+).*|\1|')
backend_protocol=$(echo "$backend_url" | sed -E 's|^(https?)://.*|\1|')
cat > "$env_local_path" << EOF
# Backend API Konfiguration
NEXT_PUBLIC_API_URL=$backend_url
# Frontend-URL für OAuth Callback
NEXT_PUBLIC_FRONTEND_URL=http://localhost:3000
# OAuth Konfiguration
NEXT_PUBLIC_OAUTH_CALLBACK_URL=http://localhost:3000/auth/login/callback
# GitHub OAuth (hardcodiert)
GITHUB_CLIENT_ID=7c5d8bef1a5519ec1fdc
GITHUB_CLIENT_SECRET=5f1e586204358fbd53cf5fb7d418b3f06ccab8fd
# Entwicklungsumgebung
NODE_ENV=development
DEBUG=true
NEXT_DEBUG=true
# Backend Host
NEXT_PUBLIC_BACKEND_HOST=$backend_host
NEXT_PUBLIC_BACKEND_PROTOCOL=$backend_protocol
EOF
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ .env.local erfolgreich erstellt/aktualisiert${NC}"
else
echo -e "${RED}✗ Fehler beim Erstellen der .env.local${NC}"
fi
echo ""
echo -e "${GREEN}Frontend-Konfiguration abgeschlossen!${NC}"
echo -e "${WHITE}Backend: $backend_url${NC}"
echo -e "${WHITE}Frontend: http://localhost:3000${NC}"
echo ""
read -p "Drücken Sie ENTER, um fortzufahren..."
}
start_debug_server() {
show_header "Debug-Server starten"
echo -e "${BLUE}Welchen Debug-Server möchten Sie starten?${NC}"
echo -e "${WHITE}1. Frontend Debug-Server (Next.js)${NC}"
echo -e "${WHITE}2. Backend Debug-Server (Flask)${NC}"
echo -e "${WHITE}3. Beide Debug-Server${NC}"
echo -e "${WHITE}4. Frontend Debug-Server (einfacher HTTP-Server)${NC}"
read -p "Wählen Sie eine Option (1-4, Standard: 1): " choice
case $choice in
1)
echo -e "${BLUE}Starte Frontend Debug-Server...${NC}"
if [ -d "frontend" ] && check_command npm; then
(cd frontend && npm run dev) &
echo -e "${GREEN}✓ Frontend Debug-Server gestartet${NC}"
else
echo -e "${RED}✗ Frontend-Verzeichnis oder npm nicht gefunden${NC}"
fi
;;
2)
echo -e "${BLUE}Starte Backend Debug-Server...${NC}"
if [ -f "backend/app/app.py" ]; then
python_cmd=""
if check_command python3; then
python_cmd="python3"
elif check_command python; then
python_cmd="python"
fi
if [ -n "$python_cmd" ]; then
$python_cmd backend/app/app.py --debug &
echo -e "${GREEN}✓ Backend Debug-Server gestartet${NC}"
else
echo -e "${RED}✗ Python nicht gefunden${NC}"
fi
else
echo -e "${RED}✗ Backend-Anwendung nicht gefunden${NC}"
fi
;;
3)
echo -e "${BLUE}Starte beide Debug-Server...${NC}"
# Backend starten
if [ -f "backend/app/app.py" ]; then
python_cmd=""
if check_command python3; then
python_cmd="python3"
elif check_command python; then
python_cmd="python"
fi
if [ -n "$python_cmd" ]; then
$python_cmd backend/app/app.py --debug &
echo -e "${GREEN}✓ Backend Debug-Server gestartet${NC}"
fi
fi
# Frontend starten
if [ -d "frontend" ] && check_command npm; then
(cd frontend && npm run dev) &
echo -e "${GREEN}✓ Frontend Debug-Server gestartet${NC}"
fi
;;
4)
echo -e "${BLUE}Starte einfachen HTTP Debug-Server...${NC}"
debug_server_dir="frontend/debug-server"
if [ -d "$debug_server_dir" ] && check_command node; then
node "$debug_server_dir/src/app.js" &
echo -e "${GREEN}✓ Einfacher Debug-Server gestartet${NC}"
else
echo -e "${RED}✗ Debug-Server-Verzeichnis oder Node.js nicht gefunden${NC}"
fi
;;
*)
echo -e "${RED}Ungültige Option${NC}"
;;
esac
echo ""
echo -e "${BLUE}Debug-Server-URLs:${NC}"
echo -e "${WHITE}- Frontend: http://localhost:3000${NC}"
echo -e "${WHITE}- Backend: https://localhost:443${NC}"
echo -e "${WHITE}- Debug-Server: http://localhost:8080${NC}"
echo ""
read -p "Drücken Sie ENTER, um fortzufahren..."
}
show_ssl_status() {
show_header "SSL-Zertifikat-Status"
cert_paths=(
"backend/instance/ssl/myp.crt"
"backend/instance/ssl/myp.key"
"frontend/ssl/myp.crt"
"frontend/ssl/myp.key"
)
echo -e "${BLUE}Prüfe SSL-Zertifikate...${NC}"
echo ""
for cert_path in "${cert_paths[@]}"; do
if [ -f "$cert_path" ]; then
echo -e "${GREEN}✓ Gefunden: $cert_path${NC}"
# Zertifikatsinformationen anzeigen (falls OpenSSL verfügbar)
if check_command openssl && [[ "$cert_path" == *.crt ]]; then
cert_info=$(openssl x509 -in "$cert_path" -noout -subject -dates 2>/dev/null)
if [ -n "$cert_info" ]; then
echo -e "${WHITE} $cert_info${NC}"
fi
fi
else
echo -e "${RED}✗ Fehlt: $cert_path${NC}"
fi
done
echo ""
echo -e "${BLUE}SSL-Konfiguration in settings.py:${NC}"
settings_path="backend/app/config/settings.py"
if [ -f "$settings_path" ]; then
if grep -q "SSL_ENABLED.*=.*True" "$settings_path"; then
echo -e "${GREEN}✓ SSL ist aktiviert${NC}"
else
echo -e "${YELLOW}⚠ SSL ist deaktiviert${NC}"
fi
else
echo -e "${RED}✗ settings.py nicht gefunden${NC}"
fi
echo ""
read -p "Drücken Sie ENTER, um fortzufahren..."
}
install_myp_complete() {
show_header "Vollständige MYP-Installation"
echo -e "${BLUE}Diese Funktion führt eine vollständige MYP-Installation durch:${NC}"
echo -e "${WHITE}1. Systemvoraussetzungen prüfen${NC}"
echo -e "${WHITE}2. Python-Abhängigkeiten installieren${NC}"
echo -e "${WHITE}3. Node.js-Abhängigkeiten installieren${NC}"
echo -e "${WHITE}4. SSL-Zertifikate erstellen${NC}"
echo -e "${WHITE}5. Datenbank initialisieren${NC}"
echo -e "${WHITE}6. Konfigurationsdateien erstellen${NC}"
echo ""
read -p "Möchten Sie fortfahren? (j/n, Standard: j): " confirm
if [ "$confirm" = "n" ]; then
return
fi
# 1. Systemvoraussetzungen prüfen
echo -e "${BLUE}1. Prüfe Systemvoraussetzungen...${NC}"
python_cmd=""
pip_cmd=""
if check_command python3; then
python_cmd="python3"
elif check_command python; then
python_cmd="python"
else
echo -e "${RED}✗ Python nicht gefunden. Bitte installieren Sie Python 3.6+.${NC}"
return 1
fi
if check_command pip3; then
pip_cmd="pip3"
elif check_command pip; then
pip_cmd="pip"
else
echo -e "${RED}✗ pip nicht gefunden. Bitte installieren Sie pip.${NC}"
return 1
fi
# 2. Python-Abhängigkeiten installieren
echo -e "${BLUE}2. Installiere Python-Abhängigkeiten...${NC}"
if [ -f "backend/requirements.txt" ]; then
exec_command "$pip_cmd install -r backend/requirements.txt" "Installiere Backend-Abhängigkeiten"
else
echo -e "${YELLOW}⚠ requirements.txt nicht gefunden${NC}"
fi
# 3. Node.js-Abhängigkeiten installieren
if check_command node && check_command npm; then
echo -e "${BLUE}3. Installiere Node.js-Abhängigkeiten...${NC}"
if [ -f "frontend/package.json" ]; then
exec_command "cd frontend && npm install" "Installiere Frontend-Abhängigkeiten"
else
echo -e "${YELLOW}⚠ package.json nicht gefunden${NC}"
fi
else
echo -e "${YELLOW}3. Überspringe Node.js-Abhängigkeiten (Node.js/npm nicht gefunden)${NC}"
fi
# 4. SSL-Zertifikate erstellen
echo -e "${BLUE}4. Erstelle SSL-Zertifikate...${NC}"
create_ssl_certificates
# 5. Datenbank initialisieren
echo -e "${BLUE}5. Initialisiere Datenbank...${NC}"
if [ -f "backend/app/models.py" ]; then
exec_command "cd backend && $python_cmd -c 'from app.models import init_db, create_initial_admin; init_db(); create_initial_admin()'" "Initialisiere Datenbank"
fi
# 6. Konfigurationsdateien erstellen
echo -e "${BLUE}6. Erstelle Konfigurationsdateien...${NC}"
setup_backend_url "https://localhost:443"
echo ""
echo -e "${GREEN}✓ Vollständige MYP-Installation abgeschlossen!${NC}"
echo ""
echo -e "${BLUE}Nächste Schritte:${NC}"
echo -e "${WHITE}1. Backend starten: python backend/app/app.py${NC}"
echo -e "${WHITE}2. Frontend starten: cd frontend && npm run dev${NC}"
echo -e "${WHITE}3. Anwendung öffnen: https://localhost:443${NC}"
echo ""
read -p "Drücken Sie ENTER, um fortzufahren..."
}
create_ssl_certificates() { create_ssl_certificates() {
show_header "SSL-Zertifikat-Generator" show_header "SSL-Zertifikat-Generator"
@ -596,9 +986,10 @@ start_application() {
echo -e "${WHITE}3. Beide Server starten (in separaten Terminals)${NC}" echo -e "${WHITE}3. Beide Server starten (in separaten Terminals)${NC}"
echo -e "${WHITE}4. Mit Docker Compose starten${NC}" echo -e "${WHITE}4. Mit Docker Compose starten${NC}"
echo -e "${WHITE}5. Vollständige Installation und Start${NC}" echo -e "${WHITE}5. Vollständige Installation und Start${NC}"
echo -e "${WHITE}6. Zurück zum Hauptmenü${NC}" echo -e "${WHITE}6. Debug-Server starten${NC}"
echo -e "${WHITE}7. Zurück zum Hauptmenü${NC}"
read -p "Wählen Sie eine Option (1-6): " choice read -p "Wählen Sie eine Option (1-7): " choice
case $choice in case $choice in
1) 1)
@ -658,29 +1049,12 @@ start_application() {
fi fi
;; ;;
5) 5)
echo -e "${BLUE}Führe vollständige Installation durch...${NC}" install_myp_complete
setup_environment
create_ssl_certificates
echo -e "${BLUE}Starte Anwendung...${NC}"
python_cmd=""
if check_command python3; then
python_cmd="python3"
elif check_command python; then
python_cmd="python"
fi
if [ -n "$python_cmd" ]; then
$python_cmd backend/app/app.py &
fi
if check_command npm; then
(cd frontend && npm run dev) &
fi
echo -e "${GREEN}Vollständige Installation und Start abgeschlossen!${NC}"
;; ;;
6) 6)
start_debug_server
;;
7)
return return
;; ;;
*) *)
@ -711,6 +1085,7 @@ show_project_info() {
echo -e "${BLUE}Standard-Zugangsdaten:${NC}" echo -e "${BLUE}Standard-Zugangsdaten:${NC}"
echo -e "${WHITE}- Admin E-Mail: admin@mercedes-benz.com${NC}" echo -e "${WHITE}- Admin E-Mail: admin@mercedes-benz.com${NC}"
echo -e "${WHITE}- Admin Passwort: 744563017196A${NC}" echo -e "${WHITE}- Admin Passwort: 744563017196A${NC}"
echo -e "${WHITE}- Router Passwort: vT6Vsd^p${NC}"
echo "" echo ""
echo -e "${BLUE}URLs:${NC}" echo -e "${BLUE}URLs:${NC}"
echo -e "${WHITE}- Backend: https://localhost:443 oder https://raspberrypi:443${NC}" echo -e "${WHITE}- Backend: https://localhost:443 oder https://raspberrypi:443${NC}"
@ -738,6 +1113,12 @@ clean_old_files() {
"frontend/https-setup.sh" "frontend/https-setup.sh"
"frontend/start-debug-server.sh" "frontend/start-debug-server.sh"
"frontend/start-frontend-server.sh" "frontend/start-frontend-server.sh"
"frontend/check-backend-connection.sh"
"frontend/setup-backend-url.sh"
"frontend/start-debug-server.bat"
"backend/setup_myp.sh"
"backend/install/create_ssl_cert.sh"
"backend/install/ssl_check.sh"
) )
for file in "${files_to_delete[@]}"; do for file in "${files_to_delete[@]}"; do
@ -765,12 +1146,16 @@ show_main_menu() {
echo -e "${WHITE}3. SSL-Zertifikate erstellen${NC}" echo -e "${WHITE}3. SSL-Zertifikate erstellen${NC}"
echo -e "${WHITE}4. Umgebung einrichten (Abhängigkeiten installieren)${NC}" echo -e "${WHITE}4. Umgebung einrichten (Abhängigkeiten installieren)${NC}"
echo -e "${WHITE}5. Anwendung starten${NC}" echo -e "${WHITE}5. Anwendung starten${NC}"
echo -e "${WHITE}6. Projekt-Informationen anzeigen${NC}" echo -e "${WHITE}6. Backend-Verbindung testen${NC}"
echo -e "${WHITE}7. Alte Dateien bereinigen${NC}" echo -e "${WHITE}7. Backend-URL konfigurieren${NC}"
echo -e "${WHITE}8. Beenden${NC}" echo -e "${WHITE}8. SSL-Zertifikat-Status anzeigen${NC}"
echo -e "${WHITE}9. Vollständige MYP-Installation${NC}"
echo -e "${WHITE}10. Projekt-Informationen anzeigen${NC}"
echo -e "${WHITE}11. Alte Dateien bereinigen${NC}"
echo -e "${WHITE}12. Beenden${NC}"
echo "" echo ""
read -p "Wählen Sie eine Option (1-8): " choice read -p "Wählen Sie eine Option (1-12): " choice
case $choice in case $choice in
1) 1)
@ -794,14 +1179,30 @@ show_main_menu() {
show_main_menu show_main_menu
;; ;;
6) 6)
show_project_info test_backend_connection
show_main_menu show_main_menu
;; ;;
7) 7)
clean_old_files setup_backend_url
show_main_menu show_main_menu
;; ;;
8) 8)
show_ssl_status
show_main_menu
;;
9)
install_myp_complete
show_main_menu
;;
10)
show_project_info
show_main_menu
;;
11)
clean_old_files
show_main_menu
;;
12)
echo -e "${GREEN}Auf Wiedersehen!${NC}" echo -e "${GREEN}Auf Wiedersehen!${NC}"
exit 0 exit 0
;; ;;