Aufräumen: totes/unbenutztes entfernt, Beispiele verallgemeinert
- create_user.py entfernt: legte nur Nicht-Admin-Benutzer per CLI an, vollständig durch die Web-UI (Einstellungen -> Benutzer, unterstützt zusätzlich Vor-/Nachname und Gruppenzuordnung) abgedeckt und von nirgends (install.sh, README, systemd-Units) referenziert - Ungenutzten Flask-Import send_from_directory entfernt (nie aufgerufen) - Drei ungenutzte CSS-Regeln entfernt (in keinem Template/JS mehr referenziert): .btn-ghost, .dc-status (Karten-Layout hat kein .dc-status-Element mehr), .nav-divider - Platzhalter für die manuelle DHCP-Reservierung nutzte als einziger im ganzen Projekt "192.168.80.x" statt der überall sonst verwendeten generischen Beispiel-Range "192.168.1.x" -- war ein Rest aus dem Testen gegen die konkrete Test-VM, jetzt vereinheitlicht - Zwei nicht versionierte, lokale Log-Dateien (mini.log, server.log) aus dem Projektverzeichnis entfernt Systematisch geprüft und dabei nichts Weiteres gefunden: alle 16 Templates werden tatsächlich gerendert, alle Imports (bis auf den einen oben) werden verwendet, keine toten Hilfsfunktionen in app.py (die drei Kandidaten aus einer AST-Analyse -- __getattr__, avatar_url, display_name -- sind über Jinja-Attributzugriff bzw. als Python-Dunder-Methode tatsächlich in Gebrauch), requirements.txt enthält nur echte direkte + transitive Abhängigkeiten. Live verifiziert: alle 14 Hauptseiten liefern nach dem Deploy weiterhin HTTP 200, keine Fehler im journalctl-Log. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@ Switch-/User-Verwaltung, Live-Log, Settings, manueller PoE-Neustart),
|
|||||||
lediglich mit modernisiertem Frontend und aufgeräumten/konfigurierbaren
|
lediglich mit modernisiertem Frontend und aufgeräumten/konfigurierbaren
|
||||||
Pfaden im Backend.
|
Pfaden im Backend.
|
||||||
"""
|
"""
|
||||||
from flask import Flask, render_template, request, redirect, url_for, flash, jsonify, send_from_directory
|
from flask import Flask, render_template, request, redirect, url_for, flash, jsonify
|
||||||
from flask_login import LoginManager, login_user, login_required, logout_user, UserMixin, current_user
|
from flask_login import LoginManager, login_user, login_required, logout_user, UserMixin, current_user
|
||||||
from flask_bcrypt import Bcrypt
|
from flask_bcrypt import Bcrypt
|
||||||
from flask_sock import Sock
|
from flask_sock import Sock
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Legt einen normalen (Nicht-Admin) Benutzer im PoE Manager an."""
|
|
||||||
import os
|
|
||||||
import sqlite3
|
|
||||||
from getpass import getpass
|
|
||||||
from flask_bcrypt import Bcrypt
|
|
||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
DB_PATH = os.environ.get("POE_DB_PATH", os.path.join(BASE_DIR, "sqlite.db"))
|
|
||||||
bcrypt = Bcrypt()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
username = input("Benutzername: ").strip()
|
|
||||||
password = getpass("Passwort: ")
|
|
||||||
password_confirm = getpass("Passwort bestätigen: ")
|
|
||||||
|
|
||||||
if password != password_confirm:
|
|
||||||
print("Passwörter stimmen nicht überein!")
|
|
||||||
return
|
|
||||||
|
|
||||||
pw_hash = bcrypt.generate_password_hash(password).decode("utf-8")
|
|
||||||
|
|
||||||
conn = sqlite3.connect(DB_PATH)
|
|
||||||
cur = conn.cursor()
|
|
||||||
try:
|
|
||||||
cur.execute(
|
|
||||||
"INSERT INTO users (username, password, is_admin) VALUES (?, ?, ?)",
|
|
||||||
(username, pw_hash, 0),
|
|
||||||
)
|
|
||||||
conn.commit()
|
|
||||||
print(f"Benutzer '{username}' erfolgreich angelegt.")
|
|
||||||
except sqlite3.IntegrityError:
|
|
||||||
print("Benutzername existiert bereits!")
|
|
||||||
finally:
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@@ -165,12 +165,6 @@ button { font-family: inherit; }
|
|||||||
}
|
}
|
||||||
.nav-item.active svg { opacity: 1; }
|
.nav-item.active svg { opacity: 1; }
|
||||||
|
|
||||||
.nav-divider {
|
|
||||||
height: 1px;
|
|
||||||
background: var(--border-soft);
|
|
||||||
margin: 10px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nav-Gruppe mit Untermenü (z.B. "Logs" -> Live-Log / Änderungslog) */
|
/* Nav-Gruppe mit Untermenü (z.B. "Logs" -> Live-Log / Änderungslog) */
|
||||||
.nav-group-toggle {
|
.nav-group-toggle {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -406,9 +400,6 @@ button { font-family: inherit; }
|
|||||||
.btn-danger { background: transparent; color: var(--danger); border-color: var(--danger-dim); }
|
.btn-danger { background: transparent; color: var(--danger); border-color: var(--danger-dim); }
|
||||||
.btn-danger:hover { background: var(--danger-dim); }
|
.btn-danger:hover { background: var(--danger-dim); }
|
||||||
|
|
||||||
.btn-ghost { background: transparent; color: var(--text-dim); border-color: transparent; }
|
|
||||||
.btn-ghost:hover { background: var(--bg-card-hover); color: var(--text); }
|
|
||||||
|
|
||||||
.btn-sm { padding: 6px 12px; font-size: 12.5px; border-radius: 8px; }
|
.btn-sm { padding: 6px 12px; font-size: 12.5px; border-radius: 8px; }
|
||||||
.btn-block { width: 100%; }
|
.btn-block { width: 100%; }
|
||||||
.btn:disabled {
|
.btn:disabled {
|
||||||
@@ -674,8 +665,6 @@ button { font-family: inherit; }
|
|||||||
}
|
}
|
||||||
.device-card .dc-ip { color: var(--text-faint); font-size: 11.5px; margin-top: 2px; font-family: var(--font-mono); }
|
.device-card .dc-ip { color: var(--text-faint); font-size: 11.5px; margin-top: 2px; font-family: var(--font-mono); }
|
||||||
|
|
||||||
.device-card .dc-status { margin-top: 12px; }
|
|
||||||
|
|
||||||
.spinner {
|
.spinner {
|
||||||
width: 13px; height: 13px;
|
width: 13px; height: 13px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|||||||
@@ -531,7 +531,7 @@
|
|||||||
<input type="text" name="mac" required placeholder="z.B. AA:BB:CC:DD:EE:FF">
|
<input type="text" name="mac" required placeholder="z.B. AA:BB:CC:DD:EE:FF">
|
||||||
</div>
|
</div>
|
||||||
<div class="field"><label>IP-Adresse</label>
|
<div class="field"><label>IP-Adresse</label>
|
||||||
<input type="text" name="ip" required placeholder="z.B. 192.168.80.50">
|
<input type="text" name="ip" required placeholder="z.B. 192.168.1.50">
|
||||||
<div class="field-hint">Muss in einem der oben konfigurierten Subnetze liegen, sonst wird sie beim Schreiben übersprungen.</div>
|
<div class="field-hint">Muss in einem der oben konfigurierten Subnetze liegen, sonst wird sie beim Schreiben übersprungen.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field"><label>Name</label>
|
<div class="field"><label>Name</label>
|
||||||
|
|||||||
Reference in New Issue
Block a user