From 57e306db082e78187390d20c5fb8ad274b73ad2e Mon Sep 17 00:00:00 2001 From: Till Tomczak Date: Mon, 26 May 2025 12:24:43 +0200 Subject: [PATCH] "feat: Implement printer management --- backend/app/app.py | 150 --------- backend/app/clean_and_add_printers.py | 110 ++++++ backend/app/config/settings.py | 99 +----- backend/app/create_ssl_cert.py | 4 +- backend/app/database/myp.db | Bin 32768 -> 32768 bytes backend/app/templates/admin.html | 265 +++++++++++++++ backend/app/utils/ssl_manager.py | 4 +- backend/generate_mercedes_cert.py | 171 ---------- backend/generate_ssl_cert.py | 261 --------------- frontend/configure_ssl.js | 4 +- myp_installer.sh | 459 ++++++++++++++++++++++++-- 11 files changed, 824 insertions(+), 703 deletions(-) create mode 100644 backend/app/clean_and_add_printers.py delete mode 100644 backend/generate_mercedes_cert.py delete mode 100644 backend/generate_ssl_cert.py diff --git a/backend/app/app.py b/backend/app/app.py index ed0ad7f3..00e27a7b 100644 --- a/backend/app/app.py +++ b/backend/app/app.py @@ -1923,154 +1923,4 @@ def validate_ssl_certificate(): except Exception as 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 \ No newline at end of file diff --git a/backend/app/clean_and_add_printers.py b/backend/app/clean_and_add_printers.py new file mode 100644 index 00000000..0d3278df --- /dev/null +++ b/backend/app/clean_and_add_printers.py @@ -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() \ No newline at end of file diff --git a/backend/app/config/settings.py b/backend/app/config/settings.py index 73ac9e6c..a7e61d33 100644 --- a/backend/app/config/settings.py +++ b/backend/app/config/settings.py @@ -128,95 +128,22 @@ def get_ssl_context(): def create_simple_ssl_cert(): """ - Erstellt ein einfaches selbstsigniertes Zertifikat mit Python. - Dies ist ein Fallback, falls OpenSSL nicht verfügbar ist. + Erstellt ein Mercedes-Benz SSL-Zertifikat mit dem neuen SSL-Manager. """ try: - import datetime - import socket - 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 - - # 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)) + # Verwende den neuen SSL-Manager + from utils.ssl_manager import ssl_manager + success = ssl_manager.generate_mercedes_certificate() - print(f"Verbessertes selbstsigniertes Zertifikat erstellt: {SSL_CERT_PATH}") - print(f"Gültig bis: {valid_until.strftime('%d.%m.%Y')}") - - except ImportError: - print("Konnte keine SSL-Zertifikate erstellen: cryptography-Paket nicht installiert") + if success: + print(f"Mercedes-Benz SSL-Zertifikat erfolgreich erstellt: {SSL_CERT_PATH}") + return True + else: + 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 except Exception as e: print(f"Fehler beim Erstellen der SSL-Zertifikate: {e}") diff --git a/backend/app/create_ssl_cert.py b/backend/app/create_ssl_cert.py index 900f1c34..7521c74e 100644 --- a/backend/app/create_ssl_cert.py +++ b/backend/app/create_ssl_cert.py @@ -86,8 +86,8 @@ if __name__ == "__main__": import argparse 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("-k", "--key", default="instance/ssl/myp.key", help="Pfad zur Schlüsseldatei") + parser.add_argument("-c", "--cert", default="../certs/myp.crt", help="Pfad zur Zertifikatsdatei") + 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") args = parser.parse_args() diff --git a/backend/app/database/myp.db b/backend/app/database/myp.db index 4f39ec20039f92715dfebc53beff7c2510506b19..4636c483e5cdaaf4939da71188a73687d79cf806 100644 GIT binary patch delta 1458 zcmb`HKT9J)7{({rBwk`RbHarc|B#@CAh?-%_wQ^YB9=xGRIoB)ihx=Kxvj)>wjRqB z2iNF9;I282`v6w9iiL&PTz{3{z}YduA(sBOf4tc ze|Fo86Y~h4;X>hSVM_m@&*z%2=kM6Zjof&c*HNix%vI(Lqm*4*Z#IsO>&>zo-L1}S zx+EYjWnfa*H;GA!TiZWu9KAd~*BS@4y@NUsa2ANO0B)H=05q^Y(`VFmC_?FCKRdcz zHKLuWzU^?jBh&4H>4doqq15+&dfDca7xyjZ2jB$uQn11Y;v!oXS%Zrx^SEeMA+m%B zWRb;1mMnrnMLq*Y5Ym1rL=au9&2Dit$Y?q++9v=UO%-Swe?xRr)zg&oY4opZOxNNc z8)k-F3kaxZdN#8yCrqo@@2W+YPJAa!sp!M1MMva&6hciY8d5E~B4A#aREpkQiw@f3 zI}|3AXhkiSMJ*Kj-lf^h&mn{|_ypnq_#R*3pE$xN^5HkmL*cZjRTA>jh)X8VUwx8O zaXF0g^ifX5CdZm_xZg?M8=@bsIU($l!;Bg!E%y{Q-?-J6ObQoX4dLhDV% U5XnzkCEFb$8{bG`+b(y@&(UvY&;S4c delta 691 zcma)(KTE?v7>DzxDO5<#qUDr21eZ=tbCPEd^bKC_jqf1&#=71*}O}bj(P|Y!CU^Lat}o7P9f>)$L#? z#$CUEGZ)17s%^b>*Z@Cy#pQc)VgM144xT9+*WM0Il9q6vYkhGA)n1qj$ z3jd1ra~!h3U2I6!Z|J0I9_`H0``Y}DR>X~Xbw8Xcc?cH$PR{gh;4uH6L1+DbD3x<) z{+vL5kQjxKIZYlXkggEu(hW(HieMxG4t~Hp_ypfzG%K3}a9>dya_-&5ztr~_ri=tE gLQMQhTTX@e!g4CSsmrO5plqv+(jpg&8(w Logs + + + + + SSL + @@ -658,11 +664,270 @@ + {% endif %} + + + {% if active_tab == 'ssl' %} +
+
+

SSL-Zertifikatsverwaltung

+ +
+ +
+ +
+

Aktuelles Zertifikat

+
+
+
+

Lade Zertifikatsinformationen...

+
+
+
+ + +
+

Zertifikatsverwaltung

+
+ + + + + + + +
+
+
+ + +
+

Erweiterte Optionen

+
+
+ + +
+
+ + +
+
+
+
{% endif %} + + + {% endblock %} {% block scripts %} diff --git a/backend/app/utils/ssl_manager.py b/backend/app/utils/ssl_manager.py index 0dce9c94..ff6e684d 100644 --- a/backend/app/utils/ssl_manager.py +++ b/backend/app/utils/ssl_manager.py @@ -79,8 +79,8 @@ class SSLCertificateManager: """Entfernt alte Zertifikate und veraltete Verzeichnisse""" # Alte SSL-Verzeichnisse löschen old_ssl_dirs = [ - os.path.join(os.path.dirname(self.certs_dir), "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", "instance", "ssl"), + os.path.join(os.path.dirname(os.path.dirname(self.certs_dir)), "app", "certs") ] for old_dir in old_ssl_dirs: diff --git a/backend/generate_mercedes_cert.py b/backend/generate_mercedes_cert.py deleted file mode 100644 index c2d99c4a..00000000 --- a/backend/generate_mercedes_cert.py +++ /dev/null @@ -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) \ No newline at end of file diff --git a/backend/generate_ssl_cert.py b/backend/generate_ssl_cert.py deleted file mode 100644 index 765a9d07..00000000 --- a/backend/generate_ssl_cert.py +++ /dev/null @@ -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.") \ No newline at end of file diff --git a/frontend/configure_ssl.js b/frontend/configure_ssl.js index 79c69442..713b8442 100644 --- a/frontend/configure_ssl.js +++ b/frontend/configure_ssl.js @@ -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...'); // Versuche, die Zertifikate aus dem Backend zu kopieren - const backendCertPath = path.join('..', 'backend', 'app', 'instance', 'ssl', 'myp.crt'); - const backendKeyPath = path.join('..', 'backend', 'app', 'instance', 'ssl', 'myp.key'); + const backendCertPath = path.join('..', 'backend', 'certs', 'myp.crt'); + const backendKeyPath = path.join('..', 'backend', 'certs', 'myp.key'); if (fs.existsSync(backendCertPath) && fs.existsSync(backendKeyPath)) { console.log('Zertifikate im Backend-Verzeichnis gefunden. Kopiere...'); diff --git a/myp_installer.sh b/myp_installer.sh index 35cfec6e..41872505 100644 --- a/myp_installer.sh +++ b/myp_installer.sh @@ -150,6 +150,14 @@ test_dependencies() { all_installed=0 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 "" if [ $all_installed -eq 1 ]; then echo -e "${GREEN}✓ Alle Abhängigkeiten sind installiert!${NC}" @@ -213,6 +221,388 @@ setup_hosts() { 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() { 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}4. Mit Docker Compose starten${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 1) @@ -658,29 +1049,12 @@ start_application() { fi ;; 5) - echo -e "${BLUE}Führe vollständige Installation durch...${NC}" - 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}" + install_myp_complete ;; 6) + start_debug_server + ;; + 7) return ;; *) @@ -711,6 +1085,7 @@ show_project_info() { echo -e "${BLUE}Standard-Zugangsdaten:${NC}" echo -e "${WHITE}- Admin E-Mail: admin@mercedes-benz.com${NC}" echo -e "${WHITE}- Admin Passwort: 744563017196A${NC}" + echo -e "${WHITE}- Router Passwort: vT6Vsd^p${NC}" echo "" echo -e "${BLUE}URLs:${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/start-debug-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 @@ -765,12 +1146,16 @@ show_main_menu() { echo -e "${WHITE}3. SSL-Zertifikate erstellen${NC}" echo -e "${WHITE}4. Umgebung einrichten (Abhängigkeiten installieren)${NC}" echo -e "${WHITE}5. Anwendung starten${NC}" - echo -e "${WHITE}6. Projekt-Informationen anzeigen${NC}" - echo -e "${WHITE}7. Alte Dateien bereinigen${NC}" - echo -e "${WHITE}8. Beenden${NC}" + echo -e "${WHITE}6. Backend-Verbindung testen${NC}" + echo -e "${WHITE}7. Backend-URL konfigurieren${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 "" - read -p "Wählen Sie eine Option (1-8): " choice + read -p "Wählen Sie eine Option (1-12): " choice case $choice in 1) @@ -794,14 +1179,30 @@ show_main_menu() { show_main_menu ;; 6) - show_project_info + test_backend_connection show_main_menu ;; 7) - clean_old_files + setup_backend_url show_main_menu ;; 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}" exit 0 ;;