diff --git a/.gitignore b/.gitignore index c520d23..1644153 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ __pycache__/ !etc/systemd/system/ !etc/systemd/system/rpi*.service !etc/systemd/system/rpi*.timer +!etc/systemd/system/poe*.service !etc/nginx/ !etc/nginx/sites-enabled/ !etc/nginx/sites-enabled/default @@ -39,7 +40,8 @@ __pycache__/ !/srv/poe_manager/static/css/* !/srv/poe_manager/static/js/ !/srv/poe_manager/static/js/* - +!/srv/poe_manager/static/images/ +!/srv/poe_manager/static/images/* # Optional: SQLite DB ignorieren (falls du nicht willst, dass Passwörter im Repo landen) -# /srv/poe_manager/sqlite.db +!/srv/poe_manager/sqlite.db diff --git a/etc/systemd/system/poe_web.service b/etc/systemd/system/poe_web.service new file mode 100644 index 0000000..b8a4352 --- /dev/null +++ b/etc/systemd/system/poe_web.service @@ -0,0 +1,16 @@ +[Unit] +Description=PoE Manager Web App +After=network.target + +[Service] +Type=simple +User=root +WorkingDirectory=/srv/poe_manager +# Nutze die virtuelle Umgebung +ExecStart=/srv/poe_manager/venv/bin/python3 /srv/poe_manager/app.py +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target + diff --git a/srv/poe_manager/app.py b/srv/poe_manager/app.py index d694755..7a8b50e 100644 --- a/srv/poe_manager/app.py +++ b/srv/poe_manager/app.py @@ -47,7 +47,7 @@ def get_devices(): Liefert eine Liste aller Devices aus der Datenbank als Dictionaries. """ conn = get_db_connection() - devices = conn.execute("SELECT mac, rpi_ip, port, name, switch_hostname FROM devices").fetchall() + devices = conn.execute("SELECT mac, rpi_ip, port, name, switch_hostname, is_active FROM devices ORDER BY name ASC").fetchall() conn.close() return devices @@ -84,10 +84,16 @@ def logout(): @app.route("/") @login_required def index(): + # Geräte aus DB laden conn = sqlite3.connect("sqlite.db") c = conn.cursor() - c.execute("SELECT mac, name FROM devices") + c.execute("SELECT mac, name, is_active FROM devices ORDER BY name ASC") devices = c.fetchall() + + # Intervall aus DB (Minuten) laden + c.execute("SELECT value FROM settings WHERE key='interval'") + row = c.fetchone() + interval = int(row[0]) if row else 5 # Default 5 Minuten conn.close() # Status aus letztem Log ermitteln @@ -102,7 +108,8 @@ def index(): if dev[1] in line: status_dict[dev[0]] = "online" if "erreichbar" in line else "offline" - return render_template("index.html", devices=devices, status=status_dict) + # Template rendern mit Devices, Status und Intervall + return render_template("index.html", devices=devices, status=status_dict, interval=interval) @app.route("/settings", methods=["GET", "POST"]) @login_required @@ -121,12 +128,23 @@ def settings(): if request.method == "POST": new_interval = int(request.form["interval"]) + + # Minuten und Sekunden berechnen + interval_minutes = new_interval + check_interval_seconds = new_interval * 60 + conn = sqlite3.connect("sqlite.db") c = conn.cursor() - # upsert - c.execute("INSERT INTO settings (key, value) VALUES (?, ?) " - "ON CONFLICT(key) DO UPDATE SET value=excluded.value", - ("interval", new_interval)) + # interval (Minuten) + c.execute(""" + INSERT INTO settings (key, value) VALUES (?, ?) + ON CONFLICT(key) DO UPDATE SET value=excluded.value + """, ("interval", interval_minutes)) + # check_interval (Sekunden) + c.execute(""" + INSERT INTO settings (key, value) VALUES (?, ?) + ON CONFLICT(key) DO UPDATE SET value=excluded.value + """, ("check_interval", check_interval_seconds)) conn.commit() conn.close() @@ -134,7 +152,7 @@ def settings(): import subprocess subprocess.run(["systemctl", "restart", "rpi-check.service"]) - flash(f"Intervall auf {new_interval} Minuten gesetzt und Service neu gestartet!") + flash(f"Intervall auf {interval_minutes} Minuten gesetzt und Service neu gestartet!") return redirect(url_for("settings")) return render_template("settings.html", interval=interval) @@ -145,65 +163,170 @@ def devices(): conn = get_db_connection() switches = conn.execute("SELECT hostname FROM switches").fetchall() - # Inline-Add - if request.method == 'POST' and 'add_device' in request.form: - if not current_user.is_admin: - flash("Zugriff verweigert!") - return redirect(url_for('devices')) - mac = request.form['mac'] - rpi_ip = request.form['rpi_ip'] - port = request.form['port'] - name = request.form['name'] - switch_hostname = request.form['switch_hostname'] - try: - conn.execute("INSERT INTO devices (mac, rpi_ip, port, name, switch_hostname) VALUES (?, ?, ?, ?, ?)", - (mac, rpi_ip, port, name, switch_hostname)) - conn.commit() - flash(f"Gerät {name} hinzugefügt.") - except sqlite3.IntegrityError: - flash("MAC existiert bereits oder Eingabefehler!") + if request.method == 'POST': + # ----------------------- + # Gerät hinzufügen + # ----------------------- + if 'add_device' in request.form: + if not current_user.is_admin: + flash("Zugriff verweigert!") + return redirect(url_for('devices')) - # Inline-Edit - if request.method == 'POST' and 'edit_device' in request.form: - if not current_user.is_admin: - flash("Zugriff verweigert!") - return redirect(url_for('devices')) - old_mac = request.form['old_mac'] - mac = request.form['mac'] - rpi_ip = request.form['rpi_ip'] - port = request.form['port'] - name = request.form['name'] - switch_hostname = request.form['switch_hostname'] - try: - conn.execute(""" - UPDATE devices - SET mac=?, rpi_ip=?, port=?, name=?, switch_hostname=? - WHERE mac=? - """, (mac, rpi_ip, port, name, switch_hostname, old_mac)) - conn.commit() - flash(f"Gerät {name} aktualisiert.") - except sqlite3.IntegrityError: - flash("MAC existiert bereits oder Eingabefehler!") + mac = request.form.get('mac') + rpi_ip = request.form.get('rpi_ip') + port = request.form.get('port') + name = request.form.get('name') + switch_hostname = request.form.get('switch_hostname') + is_active = 1 if 'is_active' in request.form else 0 - # Inline-Delete - if request.method == 'POST' and 'delete_device' in request.form: - if not current_user.is_admin: - flash("Zugriff verweigert!") - return redirect(url_for('devices')) - del_mac = request.form['delete_device'] - conn.execute("DELETE FROM devices WHERE mac=?", (del_mac,)) - conn.commit() - flash(f"Gerät {del_mac} gelöscht.") + if not all([mac, rpi_ip, port, name, switch_hostname]): + flash("Alle Felder müssen ausgefüllt sein!") + return redirect(url_for('devices')) + # Prüfen auf doppelte IP + ip_device = conn.execute("SELECT name FROM devices WHERE rpi_ip=?", (rpi_ip,)).fetchone() + if ip_device: + flash(f"IP-Adresse existiert bereits für Gerät '{ip_device['name']}'!") + return redirect(url_for('devices')) + + # Prüfen auf doppelte MAC + mac_device = conn.execute("SELECT name FROM devices WHERE mac=?", (mac,)).fetchone() + if mac_device: + flash(f"MAC-Adresse existiert bereits für Gerät '{mac_device['name']}'!") + return redirect(url_for('devices')) + + try: + conn.execute(""" + INSERT INTO devices (mac, rpi_ip, port, name, switch_hostname, is_active) + VALUES (?, ?, ?, ?, ?, ?) + """, (mac, rpi_ip, port, name, switch_hostname, is_active)) + conn.commit() + flash(f"Gerät {name} hinzugefügt.") + except sqlite3.IntegrityError: + flash("Fehler beim Hinzufügen des Geräts!") + + # ----------------------- + # Gerät bearbeiten + # ----------------------- + elif 'edit_device' in request.form: + if not current_user.is_admin: + flash("Zugriff verweigert!") + return redirect(url_for('devices')) + + old_mac = request.form.get('old_mac') + mac = request.form.get('mac') + rpi_ip = request.form.get('rpi_ip') + port = request.form.get('port') + name = request.form.get('name') + switch_hostname = request.form.get('switch_hostname') or None + is_active = 1 if 'is_active' in request.form else 0 + + # --- Prüfen, ob es sich um eine Switch-Änderung handelt --- + if mac is None and rpi_ip is None and port is None and name is None and switch_hostname: + # Nur den Switch ändern + device = conn.execute("SELECT name, switch_hostname FROM devices WHERE mac=?", (old_mac,)).fetchone() + + if not device: + flash("Gerät nicht gefunden!") + return redirect(url_for('devices')) + + old_switch = device['switch_hostname'] or "unbekannt" + device_name = device['name'] + + try: + conn.execute(""" + UPDATE devices + SET switch_hostname=? + WHERE mac=? + """, (switch_hostname, old_mac)) + conn.commit() + flash(f"Switch von {device_name} geändert: {old_switch} → {switch_hostname}") + except sqlite3.IntegrityError: + flash("Fehler beim Ändern des Switch!") + return redirect(url_for('devices')) + + if not all([old_mac, mac, rpi_ip, port, name]): + flash("Alle Felder müssen ausgefüllt sein!") + return redirect(url_for('devices')) + + # Prüfen auf doppelte IP außer das aktuelle Gerät + ip_device = conn.execute("SELECT name FROM devices WHERE rpi_ip=? AND mac<>?", (rpi_ip, old_mac)).fetchone() + if ip_device: + flash(f"IP-Adresse existiert bereits für Gerät '{ip_device['name']}'!") + return redirect(url_for('devices')) + + # Prüfen auf doppelte MAC außer das aktuelle Gerät + mac_device = conn.execute("SELECT name FROM devices WHERE mac=? AND mac<>?", (mac, old_mac)).fetchone() + if mac_device: + flash(f"MAC-Adresse existiert bereits für Gerät '{mac_device['name']}'!") + return redirect(url_for('devices')) + + try: + conn.execute(""" + UPDATE devices + SET mac=?, rpi_ip=?, port=?, name=?, is_active=? + WHERE mac=? + """, (mac, rpi_ip, port, name, is_active, old_mac)) + conn.commit() + flash(f"Gerät {name} aktualisiert.") + except sqlite3.IntegrityError: + flash("Fehler beim Aktualisieren des Geräts!") + + # ----------------------- + # Gerät löschen + # ----------------------- + elif 'delete_device' in request.form: + if not current_user.is_admin: + flash("Zugriff verweigert!") + return redirect(url_for('devices')) + + del_mac = request.form.get('delete_device') + if del_mac: + device = conn.execute("SELECT name FROM devices WHERE mac=?", (del_mac,)).fetchone() + hostname = device['name'] if device else del_mac + conn.execute("DELETE FROM devices WHERE mac=?", (del_mac,)) + conn.commit() + flash(f"Gerät {hostname} gelöscht.") + else: + flash("Keine MAC-Adresse übermittelt!") + + return redirect(url_for('devices')) + + # ----------------------- + # Devices für Anzeige + # ----------------------- devices = conn.execute(""" - SELECT devices.mac, devices.rpi_ip, devices.port, devices.name, switches.hostname AS switch_hostname + SELECT devices.mac, devices.rpi_ip, devices.port, devices.name, devices.is_active, + switches.hostname AS switch_hostname FROM devices - JOIN switches ON devices.switch_hostname = switches.hostname + LEFT JOIN switches ON devices.switch_hostname = switches.hostname + ORDER BY switches.hostname ASC """).fetchall() + conn.close() - interval_min = get_interval_seconds() // 60 return render_template('devices.html', devices=devices, switches=switches) +@app.route('/devices/toggle/', methods=['POST']) +@login_required +def toggle_device(mac): + if not current_user.is_admin: + return {"success": False, "msg": "Zugriff verweigert!"}, 403 + + conn = get_db_connection() + device = conn.execute("SELECT is_active, name FROM devices WHERE mac=?", (mac,)).fetchone() + + if not device: + conn.close() + return {"success": False, "msg": "Gerät nicht gefunden!"}, 404 + + new_status = 0 if device['is_active'] else 1 + conn.execute("UPDATE devices SET is_active=? WHERE mac=?", (new_status, mac)) + conn.commit() + conn.close() + + status_text = "deaktiviert" if new_status == 0 else "aktiviert" + return {"success": True, "msg": f"Gerät {device['name']} wurde {status_text}.", "new_status": new_status} + @app.route('/switches', methods=['GET', 'POST']) @login_required def switches(): @@ -247,20 +370,27 @@ def switches(): except sqlite3.IntegrityError: flash("Hostname existiert bereits oder Eingabefehler!") - # Inline-Delete - if request.method == 'POST' and 'delete_switch' in request.form: - if not current_user.is_admin: - flash("Zugriff verweigert!") - return redirect(url_for('switches')) - del_hostname = request.form['delete_switch'] - conn.execute("DELETE FROM switches WHERE hostname=?", (del_hostname,)) - conn.commit() - flash(f"Switch {del_hostname} gelöscht.") - switches = conn.execute("SELECT hostname, ip, username FROM switches").fetchall() conn.close() return render_template('switche.html', switches=switches) +@app.route('/switches/delete/', methods=['POST']) +@login_required +def delete_switch(hostname): + conn = get_db_connection() + devices = conn.execute("SELECT name FROM devices WHERE switch_hostname=?", (hostname,)).fetchall() + if devices: + device_names = [d['name'] for d in devices] + flash(f"Folgende Geräte sind noch dem Switch {hostname} zugewiesen: {', '.join(device_names)}", "danger") + conn.close() + return redirect(url_for('switches')) + + conn.execute("DELETE FROM switches WHERE hostname=?", (hostname,)) + conn.commit() + conn.close() + flash(f"Switch '{hostname}' gelöscht.", "success") + return redirect(url_for('switches')) + @app.route("/get_log") @login_required def get_log(): diff --git a/srv/poe_manager/create_db.py b/srv/poe_manager/create_db.py index 3ee92d7..3107428 100644 --- a/srv/poe_manager/create_db.py +++ b/srv/poe_manager/create_db.py @@ -15,11 +15,11 @@ CREATE TABLE IF NOT EXISTS switches ( # Devices c.execute(""" -CREATE TABLE IF NOT EXISTS devices ( +CREATE TABLE devices ( mac TEXT PRIMARY KEY, rpi_ip TEXT NOT NULL, switch_hostname TEXT NOT NULL, - port TEXT NOT NULL, + port TEXT, name TEXT NOT NULL, is_active INTEGER DEFAULT 0, FOREIGN KEY (switch_hostname) REFERENCES switches(hostname) diff --git a/srv/poe_manager/create_user.py b/srv/poe_manager/create_user.py new file mode 100755 index 0000000..ccba740 --- /dev/null +++ b/srv/poe_manager/create_user.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +import sqlite3 +from getpass import getpass +from flask_bcrypt import Bcrypt + +DB_PATH = "/srv/poe_manager/sqlite.db" +bcrypt = Bcrypt() + +def main(): + username = input("Benutzername: ") + 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() diff --git a/srv/poe_manager/generate_ips.py b/srv/poe_manager/generate_ips.py index 60ec98f..a299564 100644 --- a/srv/poe_manager/generate_ips.py +++ b/srv/poe_manager/generate_ips.py @@ -1,36 +1,26 @@ #!/usr/bin/env python3 import sqlite3 -import tempfile -import os from app import decrypt_password, DB_PATH def generate_ips_list(): conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row - # Alle Switches laden switches = {row['hostname']: row for row in conn.execute("SELECT hostname, ip, username, password FROM switches")} - - # Alle Geräte laden - devices = conn.execute("SELECT mac, rpi_ip, port, name, switch_hostname FROM devices").fetchall() + devices = conn.execute(""" + SELECT mac, rpi_ip, port, name, switch_hostname + FROM devices + WHERE is_active=1 + """).fetchall() conn.close() - tmp = tempfile.NamedTemporaryFile(delete=False, mode='w', prefix='ips_', suffix='.list') - tmp_path = tmp.name - for dev in devices: switch = switches.get(dev['switch_hostname']) if not switch: - continue # Switch existiert nicht, überspringen - + continue password = decrypt_password(switch['password']) - # Format: IP-Device:Hostname-Device:IP-Switch:Hostname-Switch:Port-Switch:Username-Switch:Password-Switch - line = f"{dev['rpi_ip']}:{dev['name']}:{switch['ip']}:{switch['hostname']}:{dev['port']}:{switch['username']}:{password}\n" - tmp.write(line) - - tmp.close() - return tmp_path + port = dev['port'] or "" + print(f"{dev['rpi_ip']}:{dev['name']}:{switch['ip']}:{switch['hostname']}:{port}:{switch['username']}:{password}") if __name__ == "__main__": - path = generate_ips_list() - print(path) # optional, gibt die Tempdatei zurück + generate_ips_list() diff --git a/srv/poe_manager/sqlite.db b/srv/poe_manager/sqlite.db index 39a3341..33d7fba 100644 Binary files a/srv/poe_manager/sqlite.db and b/srv/poe_manager/sqlite.db differ diff --git a/srv/poe_manager/static/css/style.css b/srv/poe_manager/static/css/style.css index 3ef38c5..422de38 100644 --- a/srv/poe_manager/static/css/style.css +++ b/srv/poe_manager/static/css/style.css @@ -17,7 +17,7 @@ h1, h2, h3, h4, h5, h6 { } pre { - background-color: #f8f9fa; + background-color: #f8f9fa7c; padding: 10px; border-radius: 5px; max-height: 600px; @@ -28,6 +28,11 @@ pre { margin-right: 5px; } +#dashboard-timer { + font-size: 0.9rem; + padding: 0.25rem 0.5rem; +} + .device-card { border: 1px solid #ccc; border-radius: 5px; @@ -53,7 +58,7 @@ pre { } .content-wrapper { - max-width: 1024px; + max-width: 1080px; margin-left: auto; margin-right: auto; } @@ -77,7 +82,7 @@ pre { .navbar-logo img { display: flex; justify-content: flex-start; - height: 60px; /* Logo Höhe, kann angepasst werden */ + height: 83px; /* Logo Höhe, kann angepasst werden */ } #log-container { @@ -102,3 +107,63 @@ pre { font-size: 0.9em; color: gray; } + +/* Tabelle anpassen */ +.custom-table input, +.custom-table select { + height: 28px; + padding: 0.25rem 0.5rem; + font-size: 0.9rem; +} + +/* Spaltenbreiten */ +.custom-table .col-small { + width: 140px; /* Hostname, Port */ +} + +.custom-table .col-ip { + width: 140px; /* IP-Adresse schmaler */ +} + +.custom-table .col-mac { + width: 140px; /* MAC-Adresse schmaler */ +} + + +/* Checkbox sichtbar auch bei disabled */ +.checkbox-visible:disabled { + opacity: 1; /* nicht ausgegraut */ + cursor: not-allowed; +} + +/* Aktiv-Label für Neues Gerät */ +label.text-white { + color: white !important; +} + + +.checkbox-visible:not(:checked) { + accent-color: #dc3545; /* rot wenn unchecked */ +} +.checkbox-visible:disabled { + cursor: not-allowed; + opacity: 1; /* verhindert Ausgrauen */ +} + +.custom-actions { + margin: auto 0; + background: #fff; +} + +.black { + color: #000000; +} + +.white { + color: #ffffff; +} + +button.login { + background-color: #ff7100; + border-color: #ff7300a9;; +} \ No newline at end of file diff --git a/srv/poe_manager/static/images/logo.png b/srv/poe_manager/static/images/logo.png new file mode 100644 index 0000000..fed2463 Binary files /dev/null and b/srv/poe_manager/static/images/logo.png differ diff --git a/srv/poe_manager/templates/base.html b/srv/poe_manager/templates/base.html index 586749e..64ea45d 100644 --- a/srv/poe_manager/templates/base.html +++ b/srv/poe_manager/templates/base.html @@ -19,7 +19,7 @@ Dashboard Devices {% if current_user.is_admin %} - Switches + Switche Users Live-Log Settings diff --git a/srv/poe_manager/templates/devices.html b/srv/poe_manager/templates/devices.html index 71f7539..4172023 100644 --- a/srv/poe_manager/templates/devices.html +++ b/srv/poe_manager/templates/devices.html @@ -3,32 +3,9 @@

Devices

-{% with messages = get_flashed_messages() %} - {% if messages %} -
- {% for message in messages %}{{ message }}
{% endfor %} -
- {% endif %} -{% endwith %} - {% if current_user.is_admin %} -

Neues Gerät hinzufügen

-
- -
-
-
-
-
- -
-
-
+ + {% endif %} @@ -39,45 +16,279 @@ + {% if current_user.is_admin %}{% endif %} {% if current_user.is_admin %}{% endif %} {% for d in devices %} - {% if current_user.is_admin %} - - - - - - - - - - - {% else %} - + + {% if current_user.is_admin %} + + {% endif %} {% endfor %}
MAC-Adresse Switch PortStatusAktionen
- - - - - {{ d['name'] }} {{ d['rpi_ip'] }} {{ d['mac'] }}{{ d['switch_hostname'] }}{{ d['switch_hostname'] or '-' }} {{ d['port'] }} + + + + + + + + + +
+ + +
+
+ + + + + + + + + + + {% endblock %} diff --git a/srv/poe_manager/templates/index.html b/srv/poe_manager/templates/index.html index 2e8f299..105ace2 100644 --- a/srv/poe_manager/templates/index.html +++ b/srv/poe_manager/templates/index.html @@ -1,15 +1,28 @@ {% extends "base.html" %} {% block content %} -

Dashboard

+

+ Dashboard + + Nächste Prüfung in -- Sekunden + +

{% for d in devices %}
{{ d[1] }}
- - {% if status[d[0]] %}{{ status[d[0]]|capitalize }}{% else %}unbekannt{% endif %} + + {% if d[2] == 0 %} + Deaktiviert + {% else %} + {% if status[d[0]] %}{{ status[d[0]]|capitalize }}{% else %}Unbekannt{% endif %} + {% endif %}
@@ -17,4 +30,60 @@ {% endfor %}
+ + {% endblock %} diff --git a/srv/poe_manager/templates/login.html b/srv/poe_manager/templates/login.html index 5ec164c..fdf104d 100644 --- a/srv/poe_manager/templates/login.html +++ b/srv/poe_manager/templates/login.html @@ -19,14 +19,14 @@
- +
- +
- +
diff --git a/srv/poe_manager/templates/logs.html b/srv/poe_manager/templates/logs.html index fcaf6d5..5f87f73 100644 --- a/srv/poe_manager/templates/logs.html +++ b/srv/poe_manager/templates/logs.html @@ -3,6 +3,10 @@

Live Log

+ +
@@ -11,36 +15,65 @@
- {% endblock %} diff --git a/srv/poe_manager/templates/settings.html b/srv/poe_manager/templates/settings.html index 5e80300..69703f6 100644 --- a/srv/poe_manager/templates/settings.html +++ b/srv/poe_manager/templates/settings.html @@ -5,20 +5,11 @@
- +
- -{% with messages = get_flashed_messages() %} - {% if messages %} -
- {% for message in messages %}{{ message }}
{% endfor %} -
- {% endif %} -{% endwith %} - {% endblock %} diff --git a/srv/poe_manager/templates/switche.html b/srv/poe_manager/templates/switche.html index 6f106e9..100e43e 100644 --- a/srv/poe_manager/templates/switche.html +++ b/srv/poe_manager/templates/switche.html @@ -1,19 +1,9 @@ {% extends "base.html" %} {% block content %} +

Switch Verwaltung

-

Switche

- -{% if current_user.is_admin %} -

Neuen Switch hinzufügen

-
- -
-
-
-
-
-
-{% endif %} + + @@ -21,33 +11,173 @@ - {% if current_user.is_admin %}{% endif %} + {% for s in switches %} - {% if current_user.is_admin %} - - - - - - - - - {% else %} - {% endif %} + + + + {% endfor %}
Hostname IP-Adresse UsernameAktionenAktionen
- - - {{ s['hostname'] }} {{ s['ip'] }} {{ s['username'] }} + + + + +
+ +
+
+ + + + + {% endblock %} diff --git a/srv/poe_manager/templates/users.html b/srv/poe_manager/templates/users.html index 339e0e2..d0f9488 100644 --- a/srv/poe_manager/templates/users.html +++ b/srv/poe_manager/templates/users.html @@ -11,27 +11,27 @@ - - + + {% if current_user.is_admin %}{% endif %} {% for u in users %} - - + + {% if current_user.is_admin %} -
UsernameRolleUsernameRolleAktionen
{{ u['username'] }}{% if u['is_admin'] %}Admin{% else %}User{% endif %}{{ u['username'] }}{% if u['is_admin'] %}Admin{% else %}User{% endif %} + - -
+